paperclipai/paperclip · error · Error
Could not determine remote file size for ${remotePath}
Error message
Could not determine remote file size for ${remotePath} What it means
Thrown by the readFile method of the command-managed runtime client when 'wc -c < <remotePath>' returns a value that is not a finite non-negative integer. This size probe is the first step of a chunked remote read: it determines how many dd-based chunks to fetch. If the size cannot be determined, the bounded read loop cannot proceed safely.
Source
Thrown at packages/adapter-utils/src/command-managed-runtime.ts:290
const end = Math.min(total, offset + REMOTE_WRITE_FALLBACK_DECODED_CHUNK_SIZE);
const chunk = buffer.subarray(offset, end).toString("base64");
await runShell(`base64 -d >> ${shellQuote(remoteTempPath)}`, { stdin: chunk });
await options?.onProgress?.(end, total);
}
await runShell(`mv -f ${shellQuote(remoteTempPath)} ${shellQuote(remotePath)}`);
await options?.onProgress?.(total, total);
} finally {
await bestEffortRemoveRemotePath(client, remoteTempPath);
}
},
readFile: async (remotePath, options) => {
// Chunked reads intentionally query the remote size first, even without
// a progress sink, so each sandbox RPC stays bounded and truncation is
// detected without materializing the whole file as one stdout string.
const sizeResult = await runShell(`wc -c < ${shellQuote(remotePath)}`);
const totalBytes = Number.parseInt(sizeResult.stdout.trim(), 10);
if (!Number.isFinite(totalBytes) || totalBytes < 0) {
throw new Error(`Could not determine remote file size for ${remotePath}`);
}
// Read in bounded remote chunks so the runner never has to materialize a
// single base64 stdout string for the whole archive. The client API still
// returns the decoded file as a Buffer, but every command result stays
// small enough for provider-backed sandbox RPCs.
const decodedChunks: Buffer[] = [];
let decodedSoFar = 0;
if (totalBytes === 0) {
await options?.onProgress?.(0, 0);
return Buffer.alloc(0);
}
for (let chunkIndex = 0; decodedSoFar < totalBytes; chunkIndex++) {
const result = await runShell(
`dd if=${shellQuote(remotePath)} bs=${REMOTE_READ_CHUNK_BYTES} skip=${chunkIndex} count=1 2>/dev/null | base64`,
);
const chunk = Buffer.from(result.stdout.replace(/\s+/g, ""), "base64");
if (chunk.byteLength === 0) break;View on GitHub (pinned to 67001ec6eb)
Solutions
- Verify the remote path exists and is a regular file: run 'ls -la <remotePath>' or use client.listFiles on the parent directory.
- If reading a special file (FIFO, device), read it with a different mechanism (e.g., client.run with cat) instead of readFile.
- Check the sandbox's wc implementation: run 'wc -c < /dev/null' to confirm it returns 0.
- Handle race conditions by retrying or ensuring the file is not modified/deleted during the read.
Example fix
// before: reading a non-regular file
await client.readFile('/workspace/pipe'); // FIFO -> wc returns unexpected value
// after: check file type first, use run() for special files
const result = await client.run(`file ${shellQuote(remotePath)}`);
// if special file, use cat instead:
const data = await client.run(`cat ${shellQuote(remotePath)} | base64`); Defensive patterns
Strategy: validation
Validate before calling
async function isRemoteFileReadable(client: SandboxManagedRuntimeClient, remotePath: string): Promise<boolean> {
try {
// Verify the path is a regular file and wc works
const result = await client.run(`test -f ${shellQuote(remotePath)} && wc -c < ${shellQuote(remotePath)}`);
const size = Number.parseInt(result.stdout.trim(), 10);
return Number.isFinite(size) && size >= 0;
} catch {
return false;
}
}
// Call before client.readFile:
if (!(await isRemoteFileReadable(client, remotePath))) {
throw new Error(`Remote path ${remotePath} is not a readable regular file.`);
} Try / catch
try {
const data = await client.readFile(remotePath);
} catch (error) {
if (error instanceof Error && error.message.includes('Could not determine remote file size')) {
// The file may not exist or may be a special file
// Check file type and existence, then retry or use an alternative read method
const fileInfo = await client.run(`file ${shellQuote(remotePath)} 2>&1 || echo 'missing'`);
console.error('File info:', fileInfo.stdout);
}
throw error;
} Prevention
- Before calling readFile, verify the path is a regular file using client.run('test -f <path>').
- Avoid reading special files (FIFOs, device nodes) through readFile—use client.run with cat instead.
- Check the sandbox's wc implementation with 'wc -c < /dev/null' to ensure it returns 0 for empty files.
- Handle file-not-found separately by checking existence before readFile.
When it happens
Trigger: Calling client.readFile(remotePath) when the remote 'wc -c' command output cannot be parsed as a non-negative finite integer. This happens when the file does not exist (wc prints an error and the exit code is non-zero, but the error is already caught by requireSuccessfulResult), or when wc produces unexpected output (e.g., locale-dependent formatting, a symlink loop, or a special file like /dev/zero where wc may hang or return unexpected values).
Common situations: Reading from a path that is a FIFO, device file, or other special file where wc -c behaves unexpectedly. A locale or wc implementation that formats output differently. The file was deleted between the size probe and the read. The sandbox environment has a non-standard wc binary.
Related errors
- Remote file read was truncated for ${remotePath}: ${out.byte
- ${action} failed with exit code ${result.exitCode ?? "null"}
- post-upload command cwd is not a confined absolute POSIX pat
- post-upload command cwd escapes the operation's target root:
- Timed out checking command "${command}" on sandbox target.
AI-assisted analysis of paperclipai/paperclip@67001ec6eb (2026-08-12).
Data as JSON: /api/errors/6cca697f3a7d3e6d.
Report an issue: GitHub.