Yeachan-Heo/oh-my-codex · error · Error
[native-assets] failed to download ${url} (${response.status
Error message
[native-assets] failed to download ${url} (${response.status} ${response.statusText}) What it means
A binary or archive download returned a non-OK status or had no body. This is the raw fetch inside downloadFile used to pull platform archives from the release; the message includes the failing URL and HTTP status so you can see exactly what was rejected.
Source
Thrown at src/cli/native-assets.ts:266
return manifest;
}
function isUnavailableManifestError(error: unknown): boolean {
if (!(error instanceof Error)) return false;
return /\[native-assets\] failed to fetch native release manifest/i.test(error.message)
|| /fetch failed/i.test(error.message);
}
function isUnavailableArchiveError(error: unknown): boolean {
if (!(error instanceof Error)) return false;
return /\[native-assets\] failed to download /i.test(error.message)
|| /fetch failed/i.test(error.message);
}
async function downloadFile(url: string, destinationPath: string): Promise<void> {
const response = await fetch(url);
if (!response.ok || !response.body) {
throw new Error(`[native-assets] failed to download ${url} (${response.status} ${response.statusText})`);
}
await mkdir(dirname(destinationPath), { recursive: true });
await pipeline(Readable.fromWeb(response.body), createWriteStream(destinationPath));
}
async function sha256ForFile(path: string): Promise<string> {
const hash = createHash('sha256');
hash.update(await readFile(path));
return hash.digest('hex');
}
const SIDECAR_SUFFIX = '.sha256';
const LOCK_SUFFIX = '.hydrate.lock';
const LOCK_WAIT_MS = 10_000;
const LOCK_RETRY_MS = 100;
const NATIVE_LOCK_WAIT_MS_ENV = 'OMX_NATIVE_LOCK_WAIT_MS';
View on GitHub (pinned to 3ad79a8a6f)
Solutions
- Open the URL in the message; if 404, confirm the release includes an asset for your platform.
- If 403/429, address GitHub rate limiting (wait, cache, or mirror assets internally).
- Pre-hydrate the cache in your base Docker image so runtime downloads are unnecessary.
- Point NATIVE_RELEASE_BASE_URL at an authenticated internal mirror.
Defensive patterns
Strategy: retry
Validate before calling
async function assetDownloadable(url: string): Promise<boolean> { const r = await fetch(url, { method: 'HEAD' }); return r.ok; } Try / catch
try { await hydrateNativeBinary(); } catch (e) { if (/\[native-assets\] failed to download /.test(String(e))) { /* extract URL+status; fix proxy/rate limit/missing asset */ } throw e; } Prevention
- Cache hydrated binaries in base images
- Handle GitHub rate limits by mirroring assets
- Check release assets include your platform before pinning a version
When it happens
Trigger: hydrateNativeBinary fetching an asset.download_url that returns 404 (asset missing for that platform), 403 (rate limit / private repo without auth), or a proxy/network failure producing a non-OK response.
Common situations: A platform archive (e.g. linux-arm64 musl) missing from the release; GitHub rate limits in CI; private repos where the asset URL requires authentication; expired signed URLs from a mirror.
Related errors
- [native-assets] failed to fetch native release manifest (${r
- [native-assets] downloaded archive size mismatch for ${asset
- [sparkshell] native binary not found. Checked cached/native
- Unknown adapt target: ${target}
- native_agent_canonical_invalid
AI-assisted analysis of Yeachan-Heo/oh-my-codex@3ad79a8a6f (2026-08-27).
Data as JSON: /api/errors/f296d3890e25d7e4.
Report an issue: GitHub.