can1357/oh-my-pi · error · ArchiveError
Archive file path is required
Error message
Archive file path is required
What it means
`readFile` requires a non-empty subPath; `normalizeArchiveLookupPath(subPath)` produced an empty/undefined result, so the method throws ArchiveError('Archive file path is required') before doing any lookup. This protects against silently treating an empty path as a root-like lookup (packages/utils/src/ar/reader.ts:130).
Source
Thrown at packages/utils/src/ar/reader.ts:130
name: nextSegment,
path: childPath,
isDirectory,
size: isDirectory ? 0 : (childEntry?.size ?? entry.size),
mtimeMs: childEntry?.mtimeMs ?? entry.mtimeMs,
mode: childEntry?.mode ?? entry.mode,
});
}
return [...children.values()].sort((left, right) =>
left.name.toLowerCase().localeCompare(right.name.toLowerCase()),
);
}
/** Extract one file member's bytes, following symlink aliases. */
async readFile(subPath: string): Promise<ExtractedArchiveFile> {
const normalizedPath = normalizeArchiveLookupPath(subPath);
if (!normalizedPath) {
throw new ArchiveError("Archive file path is required");
}
const resolvedPath = resolveArchiveLinkPath(this.#entries, normalizedPath, this.limits.maxLinkDepth);
if (resolvedPath === "") {
throw new ArchiveError(`Archive path '${normalizedPath}' is a directory`);
}
const entry = this.#entries.get(resolvedPath);
if (!entry) {
throw new ArchiveError(`Archive file '${normalizedPath}' not found`);
}
if (entry.isDirectory) {
throw new ArchiveError(`Archive path '${normalizedPath}' is a directory`);
}
if (!entry.storage) {
throw new ArchiveError(`Archive file '${normalizedPath}' has no readable storage`);
}
assertArchiveMemberSize(entry.size, normalizedPath, this.limits);
View on GitHub (pinned to 9690622007)
Solutions
- Pass the concrete file path stored in the archive, e.g. readFile('docs/report.pdf').
- Validate the path is a non-empty string before calling: `if (!subPath) throw ...`.
- If you meant to list the archive root, use listDirectory() (with no argument) instead of readFile('').
- Trace where the empty value comes from (unset config/CLI arg) and add an upstream default or required-arg check.
Example fix
// before
const path = process.env.REPORT_ENTRY ?? '';
const file = await reader.readFile(path); // throws when unset
// after
const path = process.env.REPORT_ENTRY;
if (!path) throw new Error('REPORT_ENTRY must name a file inside the archive');
const file = await reader.readFile(path); Defensive patterns
Strategy: validation
Validate before calling
// Require a concrete file path before calling readFile
function requireFilePath(p: string | undefined): string {
if (typeof p !== 'string' || p.trim() === '' || p === '.' || p === '/') {
throw new Error('A file path inside the archive is required');
}
return p;
}
await reader.readFile(requireFilePath(configEntryPath)); Type guard
function isNonEmptyPath(p: unknown): p is string {
return typeof p === 'string' && p.trim().length > 0;
} Try / catch
try {
return await reader.readFile(p);
} catch (err) {
if (err instanceof ArchiveError && err.message === 'Archive file path is required') {
throw new Error('No archive entry configured — set the file path (use listDirectory() for browsing)');
}
throw err;
} Prevention
- Make file paths required config/CLI values validated at startup.
- Use listDirectory() (no argument) to browse the root — never readFile('').
- Check that interpolated path variables are actually set before building calls.
- Reject paths that normalize to empty ('.', '/') at the input boundary.
When it happens
Trigger: Calling `reader.readFile('')`, `readFile(undefined as any)` where an optional path was intended for listDirectory, or a path that normalizes to empty (e.g. '.' or '/' depending on normalization).
Common situations: Config value or CLI flag left empty; template-built path where the variable was unset; copy-paste of listDirectory(undefined) usage into readFile; paths consisting only of separators/dots that normalize away.
Related errors
- Pass at least one model selector, e.g. `omp bench opus gpt-5
- No snippet provided. Pass inline text, --file <path>, or pip
- cloud start requires --repo-id, --repo-url, and --environmen
- ${status} requires a rationale
- program is required for launch
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/a62febe23d55c24e.
Report an issue: GitHub.