jackwener/OpenCLI · error · ArgumentError
file is ${stat.size} bytes, exceeds server limit ${MAX_BYTES
Error message
file is ${stat.size} bytes, exceeds server limit ${MAX_BYTES} (50 MiB). Split or compress before upload. What it means
This ArgumentError is thrown when the file to upload is larger than MAX_BYTES (50 MiB), the Slock server's attachment size limit. The CLI checks stat.size before reading the file so it fails locally with a clear message instead of a slow upload followed by a server rejection.
Source
Thrown at clis/slock/attachment-upload.js:60
args: [
{ name: 'file', positional: true, required: true, help: 'Local file path to upload (single file; max 50 MB)' },
{ name: 'channel', positional: true, required: true, help: 'channelId UUID or #name — server requires the attachment be scoped to a channel' },
{ name: 'server', help: 'Override active server slug' },
],
columns: ['attachmentId', 'filename', 'mimeType', 'sizeBytes'],
func: async (page, kwargs) => {
const filePath = String(kwargs.file ?? '').trim();
if (!filePath) throw new ArgumentError('file path required');
const channel = String(kwargs.channel ?? '').trim();
if (!channel) throw new ArgumentError('channel required (UUID or #name); server rejects uploads without channelId');
const abs = path.resolve(filePath);
let stat;
try { stat = fs.statSync(abs); }
catch (e) { throw new ArgumentError(`file not readable: ${abs} (${e.message})`); }
if (!stat.isFile()) throw new ArgumentError(`not a regular file: ${abs}`);
if (stat.size === 0) throw new ArgumentError(`file is empty: ${abs}`);
if (stat.size > MAX_BYTES) {
throw new ArgumentError(`file is ${stat.size} bytes, exceeds server limit ${MAX_BYTES} (50 MiB). Split or compress before upload.`);
}
const buf = fs.readFileSync(abs);
const filename = path.basename(abs);
const b64 = buf.toString('base64');
await page.goto(SLOCK_HOME_URL);
const snippet = `
${authHeadersFragment({ serverScoped: true, serverIdOverride: kwargs.server })}
${channelResolveFragment(channel)}
// multipart wants the browser to set its own boundary — strip content-type.
const uploadHeaders = { authorization: headers.authorization, accept: headers.accept };
if (headers['x-server-id']) uploadHeaders['x-server-id'] = headers['x-server-id'];
// Rebuild File from base64 → Uint8Array → Blob → File. The base64 string
// is the only path across the page boundary; JSON.stringify it (caller did)
// so injection isn't possible.
const b64 = ${JSON.stringify(b64)};View on GitHub (pinned to 49907e53dc)
Solutions
- Compress the file (zip/gz) and confirm it is now under 50 MiB, then retry.
- Split the file into chunks under 50 MiB and upload each as a separate attachment.
- Check the size first: `stat -c %s <file>` must be <= 52428800 bytes.
- If regular large uploads are needed, host the file externally (object storage) and share a link instead.
Example fix
// before
await uploadAttachment(page, '/tmp/big.dump');
// after
const fs = require('fs');
if (fs.statSync('/tmp/big.dump').size > 50 * 1024 * 1024) {
require('child_process').execSync('gzip -f /tmp/big.dump');
}
await uploadAttachment(page, '/tmp/big.dump.gz'); Defensive patterns
Strategy: validation
Validate before calling
const MAX_BYTES = 50 * 1024 * 1024;
if (fs.statSync(filePath).size > MAX_BYTES) throw new Error(`${filePath} exceeds 50 MiB server limit`); Type guard
const isWithinUploadLimit = (p, max = 50 * 1024 * 1024) => { try { return fs.statSync(p).size <= max; } catch { return false; } }; Try / catch
try {
await uploadAttachment(page, filePath);
} catch (e) {
if (e instanceof ArgumentError && e.message.includes('exceeds server limit')) {
console.error('Compress or split the file before retrying');
} else throw e;
} Prevention
- Stat file size and gzip anything over ~40 MiB before upload.
- Split large archives into <50 MiB chunks in automation.
- Keep the 50 MiB limit (52428800 bytes) as a constant in your scripts.
When it happens
Trigger: Calling attachment-upload with a file whose fs.statSync().size exceeds 50 MiB — e.g. large videos, database dumps, or bundles — while the server enforces a hard 50 MiB cap per attachment.
Common situations: Uploading build artifacts or recordings without checking size, datasets that grew since the CLI was written, or automated pipelines that attach whole log archives.
Related errors
- file is empty: ${abs}
- archive search sort must be one of ${SORT_OPTIONS.join(', ')
- archive search mediatype must be one of ${MEDIATYPES.join(',
- archive search limit must be a positive integer
- archive search limit must be <= 100
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/8e6f284b02b50314.
Report an issue: GitHub.