Skip to content

feat(deps): migrate to js-yaml v5#2197

Merged
dyoshikawa merged 1 commit into
mainfrom
resolve-issue-2122-js-yaml-v5
Jul 9, 2026
Merged

feat(deps): migrate to js-yaml v5#2197
dyoshikawa merged 1 commit into
mainfrom
resolve-issue-2122-js-yaml-v5

Conversation

@dyoshikawa

Copy link
Copy Markdown
Owner

Summary

Migrates js-yaml from 4.2.0 to 5.2.1 (a major version that was held back from the #2114 dependabot group bump due to a breaking empty-input change).

js-yaml v5 changed load("") to throw (expected a document, but the input is empty) instead of returning undefined. Several parsers here relied on the old undefined sentinel, so a naive bump broke them.

Approach

Centralized empty-input guard. Rather than patch each call site ad hoc, this adds loadYaml (src/utils/yaml.ts) — a thin wrapper that:

  • returns undefined for empty / whitespace-only / comment-only documents (matching v4), and
  • re-throws genuine parse errors unchanged (detected via YAMLException.reason === "expected a document, but the input is empty").

Every js-yaml load call now routes through loadYaml, so the v4 contract lives in one place and a future bump cannot silently reintroduce the regression.

Dependency changes:

  • js-yaml 4.2.0 → 5.2.1
  • Dropped @types/js-yaml — v5 is written in TypeScript and ships its own type declarations.

Scope of breaking changes actually hit: the codebase already used named imports (import { load, dump }), no default import, no custom Type API, and none of v5's removed dump options (styles/replacer/noCompatMode/condenseFlow/quotingType/noArrayIndent) — only lineWidth/noRefs/sortKeys, all retained. So dump needed no changes.

Bugs fixed

Beyond the two documented breakages:

  • parseApmManifest (apm-manifest.ts) — empty apm.yml now returns { dependencies: [] } instead of throwing.
  • injectSourceMetadata (gh-frontmatter.ts) — empty frontmatter block (---\n---) is treated as an empty block, not invalid frontmatter.

…the migration also fixed several undocumented sites with the same "empty file parses to undefined/null" assumption inside a try/catch: goose-command, goose-mcp, goose-subagent, roo-subagent (an empty file would have thrown a "Failed to parse …" error under a naive v5 bump).

Verification

  • loadYaml unit tests cover empty / whitespace / comment-only / valid / invalid inputs.
  • Existing empty-input regression tests (apm-manifest.test.ts, gh-frontmatter.test.ts) stay green.
  • Full unit suite: 6918 pass.
  • YAML-related e2e (mcp, permissions, commands, subagents, skills): 437 pass — these assert on generated YAML byte-for-byte, empirically confirming v5 dump output is compatible across the Tool × Feature matrix.
  • pnpm cicheck green.

Note: this touches package.json / lockfile (a dependency manifest). The maintainer explicitly authorized driving this one through to merge.

Closes #2122

🤖 Generated with Claude Code

Bump js-yaml 4.2.0 -> 5.2.1 (a major version held back from the #2114
group bump). js-yaml v5 changed empty-input behavior: `load("")` now
throws ("expected a document, but the input is empty") instead of
returning `undefined`, which broke parsers relying on the old sentinel.

Changes:
- Bump js-yaml to 5.2.1 and drop @types/js-yaml (v5 ships its own types).
- Add `loadYaml` (src/utils/yaml.ts): a thin wrapper that preserves v4's
  `undefined` return for empty/whitespace/comment-only documents (v5's
  YAMLException with reason "expected a document, but the input is empty")
  while re-throwing genuine parse errors. Single choke point so a future
  bump cannot reintroduce the empty-input regression.
- Route every js-yaml `load` call through `loadYaml`. This fixes the two
  documented breakages (parseApmManifest, injectSourceMetadata) plus
  several undocumented ones that had the same "empty file parses to
  undefined/null" assumption in a try/catch (goose command/mcp/subagent,
  roo subagent). `dump` is unchanged (no removed options are used, and no
  default import / custom Type API exists in this codebase).

No dump-format audit gaps: the Tool x Feature e2e matrix asserts on
generated YAML byte-for-byte and stays green, confirming v5 `dump` output
is compatible.

Closes #2122

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@dyoshikawa dyoshikawa merged commit 43c3143 into main Jul 9, 2026
9 checks passed
@dyoshikawa

Copy link
Copy Markdown
Owner Author

@dyoshikawa Thank you!

@dyoshikawa dyoshikawa deleted the resolve-issue-2122-js-yaml-v5 branch July 9, 2026 10:11
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.

Migrate to js-yaml v5 (held back from the #2114 group bump due to breaking empty-input behavior)

2 participants