musistudio/claude-code-router · error · Error
Input image must be a non-empty regular file no larger than
Error message
Input image must be a non-empty regular file no larger than ${maxInputBytes} bytes. What it means
Each input image must be a regular, non-empty file no larger than maxInputBytes, checked with statSync after path resolution. Directories, empty files, zero-byte truncations, and oversized uploads all fail here.
Source
Thrown at packages/core/src/media/service.ts:528
private cleanup(): void {
const now = Date.now();
for (const job of this.jobStore.list()) {
if (job.artifact && Date.parse(job.artifact.expiresAt) <= now) this.artifactStore.delete(job.artifact);
}
for (const job of this.jobStore.deleteOlderThan(now - jobRetentionDays * 24 * 60 * 60 * 1000)) this.artifactStore.delete(job.artifact);
}
private validateImages(value: unknown, min: number, max: number): string[] {
const raw = typeof value === "string" ? [value] : Array.isArray(value) ? value : [];
if (raw.length < min || raw.length > max || raw.some((item) => typeof item !== "string" || !item.trim())) {
throw new Error(`images must contain between ${min} and ${max} local image paths.`);
}
const roots = mediaInputRoots(this.requireRuntimeConfig().allowedInputRoots);
return raw.map((item) => {
const resolved = realpathSync(expandHome(String(item).trim()));
if (!roots.some((root) => isPathInside(resolved, root))) throw new Error(`Input image is outside allowed roots: ${resolved}`);
const stats = statSync(resolved);
if (!stats.isFile() || stats.size <= 0 || stats.size > maxInputBytes) throw new Error(`Input image must be a non-empty regular file no larger than ${maxInputBytes} bytes.`);
if (!detectMediaType(resolved).mimeType?.startsWith("image/")) throw new Error(`Unsupported input image format: ${resolved}`);
return resolved;
});
}
private finishCanceled(job: MediaJob, message: string): MediaJob {
const next = this.jobStore.update(job.id, {
error: { code: "canceled", message, retryable: false },
finishedAt: new Date().toISOString(),
status: "canceled"
});
this.completions.get(job.id)?.resolve(next);
this.completions.delete(job.id);
return next;
}
private publicJob(job: MediaJob): PublicMediaJob {
const { artifact, idempotencyKeyHash: _idempotencyKeyHash, ...rest } = job;View on GitHub (pinned to 99f24806c6)
Solutions
- Verify the file exists and has size > 0 and <= maxInputBytes before the call
- Raise maxInputBytes in runtime config if legitimately large inputs are needed
- Ensure the path is a regular file, not a directory or FIFO
Example fix
// before images: ["/data/allowed/video.mp4"] // after images: ["/data/allowed/photo.jpg"] // size <= maxInputBytes
Defensive patterns
Strategy: validation
Validate before calling
const st = statSync(p); if (!st.isFile() || st.size === 0 || st.size > maxInputBytes) throw new RangeError(p);
Type guard
const isAcceptableImageFile = (st: { isFile(): boolean; size: number }, max: number): boolean => st.isFile() && st.size > 0 && st.size <= max; Try / catch
try { await call(); } catch (e) { if (e instanceof Error && e.message.includes("non-empty regular file")) return invalidFile(); throw e; } Prevention
- Pre-check file size before upload
- Raise maxInputBytes deliberately when needed
When it happens
Trigger: Passing a directory path, a 0-byte file, a special file, or an image larger than the configured maxInputBytes limit.
Common situations: Drag-and-drop created an empty file, download was interrupted, or multi-MB photos/videos exceed the default size cap.
Related errors
- The CCR artifact endpoint returned a non-media content type.
- The CCR media artifact exceeds the inline preview size limit
- Compressed CCR media artifacts are not accepted for inline p
- The CCR artifact response was empty.
- The CCR artifact content did not match its declared media ty
AI-assisted analysis of musistudio/claude-code-router@99f24806c6 (2026-08-27).
Data as JSON: /api/errors/cd98a6c0cf5ac09c.
Report an issue: GitHub.