🎙️ task - fix(repo): coerce empty-string homepage/description to null (perpetual UPDATE drift)
Nobody has claimed this yet.
Assessment
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Newbie friendliness
- 82/100
- Issue type
- Bug
- Clarity
- Clearly specified
- Activity status
- Quiet
- Tech stack
- github, typescript
- Domain
- backend-api-design
Research direction
Start in src/domain.operations/repo/castToDeclaredGithubRepo.ts at the homepage and description casts on lines 47-48. Inspect setRepo as well to determine whether the same normalization is needed there. Verify the fix with the reported plan, apply, and re-plan scenario, confirming that null values converge without perpetual UPDATE drift.
Written by the indexing model from the issue text.
Description
🦫🎙️ dispatch to foreman
💧 task enqueued
├─ priority = ?
├─ yieldage = ?
└─ leverage = ?
title
fix(repo): coerce empty-string homepage/description to null (perpetual UPDATE drift)
description
.what
castToDeclaredGithubRepo casts an empty-string homepage (and description) from the GitHub API to an empty string, but the natural desired value is null. The two never converge, so every declastruct plan on a DeclaredGithubRepo shows a homepage empty-string to null UPDATE, and every apply is a no-op that re-stores the empty string. The resource is never idempotent.
.where
src/domain.operations/repo/castToDeclaredGithubRepo.ts (main / 1.7.0)
description: input.description ?? null, // line 47
homepage: input.homepage ?? null, // line 48
.root-cause
GitHub's REST API returns homepage and description as an empty string for repos with no homepage/description set — NOT null. the ?? null coalesce only fires on null/undefined, so an empty string stays an empty string.
- remote casts to
homepage= empty string - a natural wish declares
homepage: null(there is no homepage) - empty string is not equal to null, so declastruct decides UPDATE, forever
.repro
- declare a
DeclaredGithubRepowithhomepage: null(repo has no homepage set on github) declastruct plan-> showshomepageempty-string vs null UPDATEdeclastruct apply-> no-op (github stores empty string again)- re-plan -> same UPDATE. never converges.
observed on ahbode/infrastructure provision/github.repo at declastruct-github 1.6.0; confirmed unchanged on main (1.7.0).
.fix
coerce empty string to null in the cast, so remote matches a null wish:
description: input.description || null, // empty string -> null
homepage: input.homepage || null, // empty string -> null
(|| null is safe here — both fields are free-text where empty string and "unset" are equivalent; there is no meaningful empty-string value to preserve.)
alternatively, if you prefer to keep ?? semantics elsewhere, an explicit input.homepage?.trim() || null also handles whitespace-only values.
.also-consider
whichever coercion you choose, apply it symmetrically on the SET side (setRepo) if it sends homepage/description, so a null wish is written consistently and a round-trip get -> cast -> set is stable.
.impact
- breaks idempotency guarantee for
DeclaredGithubRepo(always dirty) - noise in every plan; erodes trust in the KEEP vs UPDATE signal
- forces consumers to declare
homepageas an empty string (matching the buggy cast) as a workaround, which is backwards
- Dominant language
- TypeScript
- Stars
- 0
- Forks
- 0
- PR merge metrics
- No merged PRs in 30d
Getting set up
This project ships no dev container, Dockerfile or contributing guide, so setting up is up to you: start from its README, and see our first-contribution guide for the general steps.
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from ehmpathy/declastruct-github
-
Difficulty 5/5 Over a week Newbie friendliness 38/100
-
Difficulty 5/5 Over a week Newbie friendliness 42/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 45/100
All issues in ehmpathy/declastruct-github
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
Maintainers usually reply within 1 day
-
automated issue report
Difficulty 1/5 Under an hour Newbie friendliness 68/100
-
documentation
Difficulty 1/5 Under an hour Newbie friendliness 92/100
github/copilot-sdk#2804 · 1 comment ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 62/100
drizzle-team/drizzle-orm#6418 ·
Maintainers usually reply within 4 days
-
Difficulty 1/5 Under an hour Newbie friendliness 92/100
diegosouzapw/OmniRoute#15307 · 1 comment ·
Maintainers usually reply within 2 days