coleam00/Archon · error
Expected directory listing from ${url}, got a single file
Error message
Expected directory listing from ${url}, got a single file What it means
Thrown when the GitHub contents API returns a JSON object (a single file record) instead of the expected array of directory entries. The marketplace listing code calls the contents API expecting a directory; a non-array response means the URL pointed at a file, not a directory. It guards `fetchDirectoryListing`'s contract that callers receive `GitHubContentItem[]`.
Source
Thrown at packages/cli/src/commands/workflow.ts:5110
owner: string,
repo: string,
path: string,
sha: string
): Promise<GitHubContentItem[]> {
const url = `https://api.github.com/repos/${owner}/${repo}/contents/${path}?ref=${sha}`;
let res: Response;
try {
res = await fetch(url, { headers: { Accept: 'application/vnd.github.v3+json' } });
} catch (error) {
const err = error as Error;
throw new Error(`Cannot reach GitHub API: ${err.message}`);
}
if (!res.ok) {
throw new Error(`GitHub API error: HTTP ${String(res.status)} from ${url}`);
}
const data: unknown = await res.json();
if (!Array.isArray(data)) {
throw new Error(`Expected directory listing from ${url}, got a single file`);
}
return data as GitHubContentItem[];
}
/** Download a file from raw.githubusercontent.com at a pinned SHA. */
async function downloadRawFile(
owner: string,
repo: string,
filePath: string,
sha: string
): Promise<string> {
const rawUrl = `https://raw.githubusercontent.com/${owner}/${repo}/${sha}/${filePath}`;
let res: Response;
try {
res = await fetch(rawUrl);
} catch (error) {
const err = error as Error;
throw new Error(`Cannot fetch ${rawUrl}: ${err.message}`);View on GitHub (pinned to 0773b97458)
Solutions
- Fix the directory path so it points at a folder containing the workflow YAML files, not at a file
- Verify with `gh api repos/<owner>/<repo>/contents/<path>` that the endpoint returns an array
- Update the marketplace entry's sourceUrl for that workflow
- Handle the single-file shape explicitly if a file URL is legitimate input
Example fix
// before
throw new Error(`Expected directory listing from ${url}, got a single file`);
// after
if (!Array.isArray(data)) {
// treat a single-file response as a one-item listing instead of failing
return [data as GitHubContentItem];
} Defensive patterns
Strategy: type-guard
Validate before calling
const res = await fetch(url);
const data: unknown = await res.json();
if (!Array.isArray(data)) {
throw new Error(`${url} is not a directory (got ${typeof data === 'object' && data ? (data as {type?:string}).type : typeof data})`);
} Type guard
function isDirectoryListing(data: unknown): data is GitHubContentItem[] {
return Array.isArray(data) && data.every(
(i): i is GitHubContentItem => typeof i === 'object' && i !== null && 'name' in i && 'type' in i
);
} Try / catch
try {
const items = await fetchDirectoryListing(url);
} catch (e) {
if (e instanceof Error && e.message.includes('got a single file')) {
// fall back to single-file handling path
} else throw e;
} Prevention
- Use directory URLs (no file path suffix) when calling the directory-listing helper
- Probe with `gh api repos/<owner>/<repo>/contents/<path>` before wiring a new marketplace entry
- Keep marketplace sourceUrl paths pointing at folders
- Handle both file and directory shapes at the caller if inputs are mixed
When it happens
Trigger: Calling `fetchDirectoryListing` (packages/cli/src/commands/workflow.ts:5110 area) with a GitHub contents API URL whose `path` resolves to a single file, or an API endpoint that returns an object payload rather than an array.
Common situations: A marketplace `sourceUrl` or directory path in a workflow entry points at the YAML file itself instead of its containing directory; GitHub returns `{type:'file',...}` for file paths; repo layout changed so the assumed directory is now a file; a truncated/symlinked path resolves to a blob.
Related errors
- user_fetch_failed
- Workflow '${slug}' not found
- Untrusted source URL for '${slug}': ${entry.sourceUrl} Only
- Downloaded YAML is empty for '${slug}'
- Workflow '${slug}' already exists at ${destPath}. Use --forc
AI-assisted analysis of coleam00/Archon@0773b97458 (2026-09-01).
Data as JSON: /api/errors/5ef878fd7693d899.
Report an issue: GitHub.