🐛 Restore the default for --retries - #20
Merged
Merged
Conversation
`retries` was declared with a schema that rejects `undefined`, which makes the field required: every invocation that left the flag off failed with `retries: Invalid input: expected number, received undefined`, including the one this project's deploy workflow has always used. 0.2.6 accepted it, so 0.3.0 could not be adopted without editing every caller. The default cannot be a `field.default`, because it depends on `--strict`, which a field cannot see. `main.ts` already computes it once both are parsed; the schema just has to admit the absent value, so it is now `z.number().optional()` and the help text names both defaults. Closes #19
cowboyd
approved these changes
Sep 27, 2026
This was referenced Sep 28, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Motivation
Closes #19.
--retrieswas documented as optional and required in practice, so every invocation that left it off failed:0.2.6 accepts that command; 0.3.0 rejects it, which blocked adopting 0.3.0 without editing every caller — including this project's own deploy workflow.
Approach
configlierederives requiredness from the schema:required: !!validate(schema, undefined).issues. A field is required exactly when its schema rejectsundefined, andz.number()does.The fix is not a
field.default, because the default depends on--strict— 0 when strict, 3 otherwise — and a field cannot see a sibling.main.tsalready computes it once both are parsed:So the schema only has to admit the absent value:
z.number().optional(). The help text now names both defaults instead of mentioning only the strict one, and--helprenders the flag as[RETRIES]rather than<RETRIES>.Verification
Every row of the table in the issue, against the three-page test site, stdin closed:
--site … --output … --base …received undefined… --retries=3… --concurrency=75 --retries=3… --strictreceived undefinedNew
test/config.test.tscovers the deploy invocation parsing, retries staying unset so the--strict-dependent default still applies,--retriesbeing honored when passed, the concurrency and strict defaults, and--basestill being required. With the one-word fix reverted, 4 of its 6 steps fail, so it does guard the regression rather than merely passing. Suite is 30 green.Two things found on the way, not fixed here
The
received stringvariant in the issue is env, not stdin. Config values are read from the environment under bare keys —RETRIES,CONCURRENCY— with no program prefix, sincemain.tshandsDeno.env.toObject()to the parser. With the bug, an ambientRETRIESdecided which failure you got:received undefinedretries=undefinedRETRIES=7retries=7retries=7RETRIES=bananareceived stringretries=undefined(invalid source ignored)Argument parsing also finishes before
initStdinis ever reached, so stdin cannot affect it. Worth deciding separately whether bare env keys are wanted, or whether they should be prefixed.A bad invocation exits 0.
main.tsprints the parse error and falls through withoutexit(1), so a misconfigured run looks like success to CI and leaves an empty output directory. That is what made this regression dangerous in a deploy workflow rather than merely annoying. Happy to fix in a follow-up.