Skip to content

fix(socialMeta): coerced numeric/boolean override silently dropped#7692

Merged
JohnMcLear merged 2 commits intodevelopfrom
fix-7599-numeric-override
May 7, 2026
Merged

fix(socialMeta): coerced numeric/boolean override silently dropped#7692
JohnMcLear merged 2 commits intodevelopfrom
fix-7599-numeric-override

Conversation

@JohnMcLear
Copy link
Copy Markdown
Member

Summary

Action follow-up to Qodo's bug-find on #7691. Settings.coerceValue() turns numeric-looking env vars into numbers and "true"/"false" into booleans, so e.g. SOCIAL_META_DESCRIPTION=\"2026\" arrives at the resolver as the number 2026 — and the previous resolver gated on typeof override === 'string', so it silently fell back to the i18n catalog. Operator's docker config would appear broken with no log.

Resolver now accepts string | number | boolean, stringifies, and runs the same empty/whitespace-treated-as-unset check as before. null / undefined / unsupported types still fall through to the i18n catalog.

Test plan

  • 2 new unit specs: numeric override stringified; boolean override stringified
  • All 33 socialMeta-unit specs passing
  • All 15 socialMeta integration specs passing (no behaviour change for the already-covered string path)
  • Verify in docker: SOCIAL_META_DESCRIPTION=2026 → og:description renders as "2026"

🤖 Generated with Claude Code

Qodo flagged on PR #7691: Settings.coerceValue() turns numeric-looking env
vars into numbers and "true"/"false" into booleans, so e.g.
SOCIAL_META_DESCRIPTION="2026" arrives at the resolver as the number 2026.
The previous resolver gated on `typeof override === 'string'`, so it
silently fell back to the i18n catalog with no warning — the operator's
docker config would appear broken.

Accept string|number|boolean and stringify before the empty-check; null /
undefined / unsupported types still fall through to the catalog. Two new
unit specs cover the numeric and boolean coercion paths.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@qodo-code-review
Copy link
Copy Markdown

ⓘ You've reached your Qodo monthly free-tier limit. Reviews pause until next month — upgrade your plan to continue now, or link your paid account if you already have one.

@qodo-free-for-open-source-projects
Copy link
Copy Markdown

Review Summary by Qodo

Fix socialMeta resolver silently dropping coerced numeric/boolean overrides

🐞 Bug fix

Grey Divider

Walkthroughs

Description
• Accept coerced numeric/boolean overrides in socialMeta resolver
• Stringify override values before empty-check validation
• Add unit tests for numeric and boolean coercion paths
• Prevent silent fallback to i18n catalog on type mismatch
Diagram
flowchart LR
  A["Settings.coerceValue<br/>coerces env vars"] -->|"numeric/boolean<br/>override"| B["resolveDescriptionWithOverride"]
  B -->|"Accept string|number|boolean"| C["Stringify value"]
  C -->|"Non-empty after trim"| D["Return override"]
  C -->|"Empty/whitespace"| E["Fall back to i18n"]
  B -->|"null/undefined"| E
Loading

Grey Divider

File Changes

1. src/node/utils/socialMeta.ts 🐞 Bug fix +13/-6

Accept and stringify coerced numeric/boolean overrides

• Updated resolveDescriptionWithOverride to accept unknown type instead of `string | null |
 undefined`
• Added type guards to check for string, number, or boolean types before stringifying
• Enhanced comment documentation explaining Settings.ts coercion behavior and empty-value handling
• Stringify override values using String() before empty/whitespace validation

src/node/utils/socialMeta.ts


2. src/tests/backend/specs/socialMeta-unit.ts 🧪 Tests +34/-0

Add tests for numeric and boolean override coercion

• Added unit test for numeric override coercion (e.g., 2026 as number becomes "2026")
• Added unit test for boolean override coercion (e.g., true becomes "true")
• Both tests verify that coerced values are properly stringified and rendered in og:description
• Tests use type casting to simulate runtime behavior from Settings.ts coerceValue()

src/tests/backend/specs/socialMeta-unit.ts


Grey Divider

Qodo Logo

@qodo-free-for-open-source-projects
Copy link
Copy Markdown

qodo-free-for-open-source-projects Bot commented May 7, 2026

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0)

Grey Divider


Remediation recommended

1. Settings type mismatch ✓ Resolved 🐞 Bug ⚙ Maintainability
Description
Settings.coerceValue() can coerce env-var expansions (including socialMeta.description) into
number | boolean, but both SettingsType and SocialMetaSettings still declare description as
string | null, forcing unsafe casts and hiding the real contract from future callers. This
increases the chance of future runtime errors if code assumes a string and calls string methods
without guards.
Code

src/node/utils/socialMeta.ts[R170-179]

const resolveDescriptionWithOverride = (
-  override: string | null | undefined,
+  override: unknown,
locales: {[lang: string]: {[key: string]: string}} | undefined,
renderLang: string,
): string => {
-  if (typeof override === 'string' && override.trim() !== '') return override;
+  if (override !== null && override !== undefined &&
+      (typeof override === 'string' || typeof override === 'number' ||
+       typeof override === 'boolean')) {
+    const s = String(override);
+    if (s.trim() !== '') return s;
Evidence
coerceValue() converts numeric/boolean-like strings to number/boolean and is used by
lookupEnvironmentVariables() when expanding ${ENV_VAR...} in settings, so
socialMeta.description can be non-string at runtime. However, the declared types for
socialMeta.description remain string | null (both in the global Settings type and the local
narrow type in socialMeta.ts), and the new unit tests must use as unknown as string to
compile—confirming the mismatch.

src/node/utils/Settings.ts[160-170]
src/node/utils/Settings.ts[862-897]
src/node/utils/Settings.ts[899-1025]
src/node/utils/socialMeta.ts[98-107]
src/node/utils/socialMeta.ts[164-182]
src/tests/backend/specs/socialMeta-unit.ts[253-285]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`Settings.coerceValue()` can produce `number | boolean` values for env-var-expanded settings, but the TypeScript types still claim `socialMeta.description` is `string | null`. This mismatch forces unsafe casts and makes it easy for future code to accidentally assume a string.
### Issue Context
The PR mitigates the runtime issue by accepting `unknown` in `resolveDescriptionWithOverride()` and stringifying `string|number|boolean`. The type system should reflect this reality so callers and tests don’t need `as unknown as string`.
### Fix Focus Areas
- src/node/utils/Settings.ts[160-170]
- src/node/utils/Settings.ts[862-897]
- src/node/utils/socialMeta.ts[98-107]
- src/node/utils/socialMeta.ts[164-182]
- src/tests/backend/specs/socialMeta-unit.ts[253-285]
### Suggested fix
1. Update the settings type(s) to reflect runtime: `description: string | number | boolean | null` (optionally also `undefined` if applicable).
2. Update `SocialMetaSettings` in `socialMeta.ts` similarly.
3. Replace `override: unknown` with `override: string | number | boolean | null | undefined`.
4. Remove the `as unknown as string` casts from the new unit tests (they should compile with the widened types).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Qodo Logo

Action Qodo bug-find: SettingsType.socialMeta.description and
SocialMetaSettings.description still claimed `string | null`, but
Settings.coerceValue() can produce number|boolean from env-var-driven
config — the previous resolver fix was correct at runtime but the type
mismatch forced `as unknown as string` casts in the new tests.

Widen both declared types to `string | number | boolean | null` to match
runtime reality, drop the typeof string|number|boolean guards in the
resolver (the union now narrows automatically) and remove the test casts.
Behaviour is unchanged.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@JohnMcLear JohnMcLear merged commit a356414 into develop May 7, 2026
56 of 58 checks passed
@JohnMcLear JohnMcLear deleted the fix-7599-numeric-override branch May 7, 2026 10:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant