janhq/jan · warning
TOO_LARGE
Error message
TOO_LARGE
What it means
The preview loader enforces MAX_PREVIEW_BYTES twice: once via the content-length header before reading, once on the decoded text length. Exceeding either throws new Error(TOO_LARGE), which the panel renders as a 'file too large to preview' state instead of loading the content.
Solutions
- Choose a different preview mode (e.g. open externally) for large files.
- Increase MAX_PREVIEW_BYTES if legitimately larger text previews are needed.
- Range-request only the first N bytes for a truncated preview.
- Fix kind detection so binaries don't enter the text preview path.
Example fix
// before
if (size > MAX_PREVIEW_BYTES) throw new Error(TOO_LARGE)
// after
if (size > MAX_PREVIEW_BYTES) {
throw new Error(`${TOO_LARGE} (${size} > ${MAX_PREVIEW_BYTES} bytes)`)
} Defensive patterns
Strategy: validation
Validate before calling
const head = await fetch(url, { method: 'HEAD' })
const size = Number(head.headers.get('content-length') ?? 0)
if (head.ok && size > MAX_PREVIEW_BYTES) {
return { status: 'too-large' }
} Type guard
const isPreviewableSize = (size: number): boolean => Number.isFinite(size) && size > 0 && size <= MAX_PREVIEW_BYTES
Try / catch
try {
const content = await loadPreview(url)
setState({ status: 'ready', content })
} catch (err) {
if (err.message === TOO_LARGE) {
setState({ status: 'too-large' })
} else {
setState({ status: 'error', message: err.message })
}
} Prevention
- HEAD-check content-length before downloading preview bodies.
- Define a sane MAX_PREVIEW_BYTES for typical text files (logs, code, configs).
- Route binary/large files to download or external open instead of text preview.
- Treat missing content-length as unknown and cap the streamed read.
When it happens
Trigger: Opening a text preview for a file whose content-length header exceeds MAX_PREVIEW_BYTES, or whose decoded body is longer than the limit (e.g. large log, dataset, or binary file misdetected as text).
Common situations: Clicking a preview on multi-hundred-MB data files; content-length missing so the limit is only caught after downloading the whole body; binary assets routed into the text preview path.
Understand the failure class
Background: "File too large" / "file size exceeds limit" errors: why libraries cap file sizes and how to fix them — this error's family across 46 libraries.
Related errors
AI-assisted analysis of janhq/jan@7205d770c1 (2026-09-17).
Data as JSON: /api/errors/bf45449b87365d73.
Report an issue: GitHub.
Appendix: source
Thrown at web-app/src/containers/CoworkPreviewPanel.tsx:109
if (kind === 'file') {
setState({ status: 'unsupported', path })
return
}
setState({ status: 'loading', path })
void (async () => {
const url = getServiceHub().core().convertFileSrc(abs)
if (isAssetKind(kind)) {
// The element streams the file itself, so there is nothing to fetch and
// a large video costs nothing to "open".
if (alive) setState({ status: 'ready', path, kind, assetUrl: url })
return
}
try {
const res = await fetch(url)
if (!res.ok) throw new Error(String(res.status))
const size = Number(res.headers.get('content-length') ?? 0)
if (size > MAX_PREVIEW_BYTES) throw new Error(TOO_LARGE)
const content = await res.text()
if (content.length > MAX_PREVIEW_BYTES) throw new Error(TOO_LARGE)
if (!alive) return
setState({
status: 'ready',
path,
kind,
content,
unresolvedRefs: kind === 'html' ? unresolvedRefs(content) : undefined,
externalRefs: kind === 'html' ? externalRefs(content) : undefined,
})
} catch (e) {
if (!alive) return
setState({
status: 'failed',
path,
reason: e instanceof Error ? e.message : String(e),
})View on GitHub (pinned to 7205d770c1)