Skip to content

respec invocation fails with exit code 127 on every build (v2.12.5 and v2.13.0) #229

@marcoscaceres

Description

@marcoscaceres

The respec build step fails on every CI run for w3c/gamepad going back to at least 2026-02-13, both on pull_request and on push to gh-pages. The annotation is:

Command `respec -s "http://localhost:3000/index.html?gitRevision=<SHA>" \
  -o "index.html.built.html" --verbose -t 20 -e` failed with exit code: 127.

Exit 127 means respec is not on PATH when src/build.ts invokes it as a bare command:

https://github.com/w3c/spec-prod/blob/v2.13.0/src/build.ts#L102-L120

Versions confirmed broken

Pin Run
w3c/spec-prod@v2 (= v2.13.0) https://github.com/w3c/gamepad/actions/runs/25891886076
w3c/spec-prod@v2.12.5 https://github.com/w3c/gamepad/actions/runs/25893348176

Same identical failure under both. Also reproduces on push to gh-pages (https://github.com/w3c/gamepad/actions/runs/25892690820), so it's not PR-specific.

In w3c/gamepad, this has been failing on every PR run and every gh-pages push since at least 2026-02-13.

Local baseline passes

Running ReSpec locally against the same source with the same flags exits 0:

npx respec --localhost --haltonerror -s index.html -o /dev/null
# exit 0, 0 errors, only no-unused-dfns warnings

So the spec content is fine — the failure is in how the action installs or locates the respec binary.

Reproducing workflow

jobs:
  ci:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: w3c/spec-prod@v2
        with:
          VALIDATE_INPUT_MARKUP: true

Working hypothesis (please verify)

Looking at the action source (v2.13.0):

  • src/setup.ts calls install("respec", PUPPETEER_ENV) for the ReSpec toolchain
  • install() in src/utils.ts runs pnpm add respec in ACTION_DIR, then restores the original package.json and pnpm-lock.yaml to fake --no-save (workaround for Update to package.json breaks multi-spec builds #213 / fix: correctly reset pnpm-lock.yaml after package install #218)
  • src/build.ts then calls await sh('respec ...'). I checked both PUPPETEER_ENV (src/constants.ts) and sh (src/utils.ts) and neither touches PATHsh uses child_process.exec with { ...process.env, ...execOptions.env }. So the respec lookup falls through to whatever PATH the action runner inherits from pnpm/action-setup and actions/setup-node.

If pnpm add respec is silently failing or the resulting binary isn't on PATH under newer pnpm (the major jump to 10.x landed in #210, with further bumps in #217 and #225), the downstream respec lookup gets exit 127 with no upstream error surfaced.

Suggested debugging

  1. Make the install() helper throw on a non-zero exit from pnpm add instead of silently returning the output
  2. Log the pnpm add stdout/stderr when the subsequent respec command fails

Happy to test fixes or run additional reproducers.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    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