Skip to content

[BUG] Deployment fails with Unexpected token 'a' - firebase-tools output parsing is fragile #463

Description

@nvzoll

Action config

- uses: FirebaseExtended/action-hosting-deploy@v0
   with:
     repoToken: '${{ secrets.GITHUB_TOKEN }}'
     firebaseServiceAccount: '${{ secrets.<my secret>}}'
     channelId: live
     projectId: <my project>
     target: production
   env:
      FIREBASE_CLI_EXPERIMENTS: webframeworks

Error message

Deploying to production site
    /usr/local/bin/npx firebase-tools@latest deploy --only hosting:production --project ... --json

    added 1174 packages in 45s

    189 packages are looking for funding
      run `npm fund` for details
    Error: Unexpected token 'a', "
    added 1174"... is not valid JSON
    ***
      conclusion: 'failure',
      output: ***
        title: 'Deploy preview failed',
        summary: `Error: Unexpected token 'a', "\nadded 1174"... is not valid JSON`
      ***
    ***

Expected behavior

Deploying to production site
    /usr/local/bin/npx firebase-tools@latest deploy --only hosting:production --project ... --json
    npm warn exec The following package was not found and will be installed: firebase-tools@15.22.1
    npm warn deprecated node-domexception@1.0.0: Use your platform's native DOMException instead
    npm warn deprecated json-ptr@3.1.1: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.
    npm warn deprecated uuid@9.0.1: uuid@10 and below is no longer supported.  For ESM codebases, update to uuid@latest.  For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028).
    npm warn deprecated glob@10.5.0: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me
    Failed to find esbuild with npx which: Error: Command failed: npx which esbuild
    esbuild not found, installing...

    added 2 packages, and audited 1578 packages in 6s

    332 packages are looking for funding
      run `npm fund` for details

    54 vulnerabilities (2 low, 38 moderate, 11 high, 3 critical)

    To address issues that do not require attention, run:
      npm audit fix

    To address all issues (including breaking changes), run:
      npm audit fix --force

    Run `npm audit` for details.
    npm warn deprecated glob@8.1.0: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me
    npm warn deprecated google-p12-pem@4.0.1: Package is no longer maintained
    npm warn deprecated uuid@8.3.2: uuid@10 and below is no longer supported.  For ESM codebases, update to uuid@latest.  For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028).
    npm warn deprecated uuid@9.0.1: uuid@10 and below is no longer supported.  For ESM codebases, update to uuid@latest.  For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028).
    npm warn deprecated uuid@9.0.1: uuid@10 and below is no longer supported.  For ESM codebases, update to uuid@latest.  For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028).

    added 1174 packages in 45s

    189 packages are looking for funding
      run `npm fund` for details
    ***
      "status": "success",
      "result": ***
        "hosting": "projects/.../sites/.../versions/..."
      ***
    ***::endgroup::
    ***
      details_url: 'https://production.web.app/',
      conclusion: 'success',
      output: ***
        title: 'Production deploy succeeded',
        summary: '[production.web.app](https://production.web.app/)'
      ***
    ***

Actual behavior

Builds that worked with 0.10 now broken with 0.11

Investigation summary

Our firebase-tools JSON itself is valid and unchanged. The failure is in how the action captures and parses stdout.

Suspected root cause

execWithCredentials in src/deploy.ts returns only the last stdout chunk:

return deployOutputBuf.length
  ? deployOutputBuf[deployOutputBuf.length - 1].toString("utf-8")
  : "";

deployProductionSite / deployPreview then JSON.parse() that single chunk. This assumes the firebase-tools --json blob is always the last thing written to stdout.

That presumably breaks under Node 24, which bundles npm 11 (Node 20 bundled npm 10). npm's install summary (added N packages in …) and funding notice (N packages are looking for funding) are written to stdout (via npm's output() / reifyOutput). Between npm 10 and npm 11 the flush ordering of that summary relative to the npm exec-spawned child changed:

  • npm 10 (Node 20): npm's summary landed on stdout before the firebase JSON - last chunk was the JSON - parse succeeded.
  • npm 11 (Node 24): the summary is flushed after the child's output - last chunk is \nadded 1174 packages… - JSON.parse fails.

Relying on chunks is fragile. Would suggest slicing { } symbols instead.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions