install.sh fails with 'Could not find Codex package or platform npm release assets' on valid release
What happened
Running the official install script fails even though the release and its assets exist:
$ sh -c 'curl -fsSL https://chatgpt.com/codex/install.sh | CODEX_NON_INTERACTIVE=1 sh'
Could not find Codex package or platform npm release assets for Codex 0.143.0.
The release rust-v0.143.0 exists at https://github.com/openai/codex/releases/tag/rust-v0.143.0 and the asset codex-package-x86_64-unknown-linux-musl.tar.gz is present.
Root cause
The install script at https://chatgpt.com/codex/install.sh uses a hand-rolled awk-based JSON parser (function release_asset_digest_or_empty, lines 169-205) to extract asset digests from the GitHub API response. This parser is fragile:
- It tracks brace depth using a
depthvariable that is never initialized (awk defaults to 0, but the logic is still brittle). - The GitHub API returns a deeply nested JSON structure with nested objects (
uploader,label, etc.) that the simple{/}depth counter cannot reliably parse. - If the API response is malformed, truncated, or the parser fails to match, it silently returns empty — causing
release_asset_existsto return false.
The script then falls through to the else branch at line 859-861:
else
echo "Could not find Codex package or platform npm release assets for Codex $resolved_version." >&2
exit 1
fi
Reproduction
curl -fsSL https://api.github.com/repos/openai/codex/releases/latest | \
awk -v asset="codex-package-x86_64-unknown-linux-musl.tar.gz" '
/"name":[[:space:]]*"[^"]+"/ {
name = $0
sub(/^.*"name":[[:space:]]*"/, "", name)
sub(/".*$/, "", name)
if (name == asset) {
in_asset = 1
asset_depth = depth
}
}
in_asset && /"digest":[[:space:]]*"[^"]+"/ {
digest = $0
sub(/^.*"digest":[[:space:]]*"/, "", digest)
sub(/".*$/, "", digest)
}
{
line = $0
opens = gsub(/\{/, "{", line)
closes = gsub(/\}/, "}", line)
depth += opens - closes
if (in_asset && depth < asset_depth) {
in_asset = 0
}
}
END {
if (digest != "") { print digest }
}'
This returns empty because the awk parser cannot correctly navigate the nested JSON.
Suggested fix
Replace the awk-based JSON parser with jq (if available) or a more robust parsing approach. At minimum, fall back to checking browser_download_url existence via a simple grep if the digest lookup fails, since the presence of any URL is sufficient to confirm the asset exists.
Alternatively, use curl -fsSL HEAD requests to check asset availability directly:
release_asset_exists() {
asset="$1"
url="https://github.com/openai/codex/releases/download/rust-v${resolved_version}/${asset}"
curl -fsSL -o /dev/null "$url"
}
This avoids JSON parsing entirely and is much more reliable.
Environment
- OS: Debian 13 (bookworm), x86_64
- Shell: sh (dash)
- curl: available
- jq: not available on all systems
- Current codex version: 0.142.0
- Target version: 0.143.0
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗