midudev/autoskills · error · Error
download failed for
Error message
download failed for ${normalizedRel}: ${errors.join("; ")} What it means
downloadRegistryFile tries each candidate registry base URL in turn; non-fatal failures are collected into an errors array and it continues to the next URL. Only after every base URL has failed does it throw this aggregated error, joining the per-URL failure reasons (HTTP status + statusText) with semicolons.
Solutions
- Read the joined per-URL reasons in the message (e.g. '404 Not Found from ...') to see the actual HTTP failure and fix accordingly.
- Verify the skill name and relative path exist in the registry at your resolved version; correct the registry entry or upgrade/downgrade the autoskills version.
- Check AUTOSKILLS_REGISTRY_BASE_URL / registryBaseUrl points to a valid raw base ending with the skills-registry prefix.
- Fix network/proxy access to the registry host and retry; confirm the target branch/tag exists on the remote.
Example fix
// before AUTOSKILLS_REGISTRY_BASE_URL=https://raw.githubusercontent.com/org/repo/wrong-branch/packages/autoskills/skills-registry // 404 from every attempt -> 'download failed for skills/foo/SKILL.md: 404 Not Found from ...' // after AUTOSKILLS_REGISTRY_BASE_URL=https://raw.githubusercontent.com/org/repo/main/packages/autoskills/skills-registry
Defensive patterns
Strategy: try-catch
Validate before calling
// probe every candidate base URL before installing
async function baseOk(baseUrl) {
try {
const res = await fetch(`${baseUrl}/registry.json`);
return res.ok;
} catch { return false; }
} Try / catch
try {
await downloadRegistryEntry(name, entry, dest);
} catch (e) {
if (e.message.startsWith("download failed for ")) {
const reasons = e.message.split("download failed for ")[1];
logger.error("All registry mirrors failed", { reasons });
throw new Error(`Registry unreachable — check paths/network. Details: ${reasons}`);
} else throw e;
} Prevention
- Verify the skill/rel path exists in the registry manifest before attempting download.
- Point registryBaseUrl at a pinned version tag, not a mutable branch, for reproducible installs.
- Test network/proxy access to the registry host from the target environment.
- Confirm the configured base URL ends with the correct skills-registry prefix.
When it happens
Trigger: All base URLs produced by getRegistryRawBaseUrls (configured URL, or versioned + main fallback) returned non-ok responses (or otherwise failed) for the requested skill file — e.g. 404 Not Found on every mirror because the file doesn't exist in the registry at that version or branch.
Common situations: Requesting a skill/file that was renamed or removed; a pinned package version whose tag does not exist on the raw host yet; a custom AUTOSKILLS_REGISTRY_BASE_URL pointing at the wrong path or a downed mirror; offline/blocked network with proxy errors surfaced per attempt.
Understand the failure class
Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.
Related errors
AI-assisted analysis of midudev/autoskills@0ec725320d (2026-09-15).
Data as JSON: /api/errors/999c6b8c6ac515e4.
Report an issue: GitHub.
Appendix: source
Thrown at packages/autoskills/installer.ts:321
);
}
errors.push(`${res.status} ${res.statusText} from ${baseUrl}`);
opts.onTrace?.(`miss ${normalizedRel}: ${res.status} ${res.statusText} from ${baseUrl}`);
continue;
}
const buf = Buffer.from(await res.arrayBuffer());
const actual = sha256Buffer(buf);
if (actual !== expected) {
errors.push(`hash mismatch from ${baseUrl}`);
opts.onTrace?.(`hash mismatch for ${normalizedRel} from ${baseUrl}`);
continue;
}
opts.onTrace?.(`downloaded ${normalizedRel} from ${url}`);
return { buf, url };
}
throw new Error(`download failed for ${normalizedRel}: ${errors.join("; ")}`);
}
async function downloadRegistryEntry(
skillName: string,
entry: RegistryEntry,
destDir: string,
opts: InstallOptions,
): Promise<void> {
const files = [];
for (const rel of entry.files) {
files.push({
rel: normalizeRegistryRelPath(rel),
...(await downloadRegistryFile(skillName, entry, rel, opts)),
});
}
const bundleHash = createHash("sha256")
.update(View on GitHub (pinned to 0ec725320d)