Skip to content

fix(cli): guard nil file panic in generated download commands - #1241

Merged
jablan merged 1 commit into
mainfrom
fix/cli-locales-download-nil-file-panic
Sep 3, 2026
Merged

fix(cli): guard nil file panic in generated download commands#1241
jablan merged 1 commit into
mainfrom
fix/cli-locales-download-nil-file-panic

Conversation

@jablan

@jablan jablan commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

Summary

A user reported that the latest CLI release panics on phrase locales download when a --tags filter matches zero translations:

$ phrase locales download --id en-US --project_id ... -t ... --file_format properties --tags foo
panic: runtime error: invalid memory address or nil pointer dereference
...
github.com/phrase/phrase-cli/cmd.initLocaleDownload.func1(...)
        /go/src/github.com/phrase/phrase-cli/cmd/api_locales.go:410 +0xdef

This is a sibling issue to #1235 (fixed in pull.go), but in a different code path: the standalone, per-endpoint phrase locales download command generated from openapi-generator/templates/cli/api.handlebars.

Root cause: the API returns 200 OK with an empty body when a filter matches no translations. The SDK's decode() leaves the *os.File result nil in that case with no error — a valid empty export, not a failed download. The generated command unconditionally called data.Close() / data.Name() on that nil file, causing a nil pointer dereference.

Since cmd/api_*.go files are generated (and gitignored — never committed), the fix has to live in the Handlebars template itself, which is shared by every generated command whose return type is *os.File. So this also covers other download-style endpoints beyond locale download, not just the one in the report.

Fix

Wrap the file-handling block in api.handlebars with a data != nil guard, mirroring the same fix already applied to copyToDestination in pull.go.

Test plan

  • Added spec/locales_download_spec.rb, an integration spec that mocks the download endpoint returning 200 with an empty body and runs the actual built phrase-cli binary.
  • Regenerated the CLI locally (npm run generate.go && npm run generate.cli) and confirmed the new spec fails with the exact reported panic against the pre-fix template, and passes after applying the fix.
  • Confirmed normal (non-empty) downloads are unaffected.
  • Full Ruby spec suite (38 examples) green.

🤖 Generated with Claude Code

The API returns 200 with an empty body when a download's tags filter
matches zero translations. The SDK's decode() leaves the *os.File
result nil in that case with no error, but the generated download
commands unconditionally called data.Close()/data.Name() on it,
causing a nil pointer dereference panic, e.g.:

  phrase locales download --id en-US --project_id ... \
    --file_format properties --tags <tag-matching-nothing>

Same root cause as the earlier pull.go fix, but in the openapi-generator
CLI template, which is shared by every generated command whose return
type is *os.File - so this also covers other download-style endpoints
beyond locale download.

Added spec/locales_download_spec.rb, which reproduces the exact crash
against a mock server. Confirmed it fails with the reported panic
against the pre-fix generated code and passes after regenerating with
the template fix; full spec suite (38 examples) still green.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

API changelog (oasdiff)

Doc-only edits (descriptions, examples) do not appear here.

No changes detected

@jablan
jablan merged commit e8f3f61 into main Sep 3, 2026
13 checks passed
@jablan
jablan deleted the fix/cli-locales-download-nil-file-panic branch September 3, 2026 09:27
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.

2 participants