paperclipai/paperclip · error · Error
That file is empty. Choose the private key downloaded from…
Error message
That file is empty. Choose the private key downloaded from your GitHub App.
What it means
readGitHubPrivateKeyFile validates the file the user selected for a GitHub App private key before reading it. A file whose `size` is exactly 0 cannot be a valid .pem key, so the function throws immediately. This check runs before file.text() so empty selections fail fast with actionable copy.
Solutions
- Re-download the private key from the GitHub App settings page (Developper settings > GitHub Apps > your app > Private key > Generate) and select the new .pem file.
- Check the file in the picker handler and reject zero-byte files with a clear message before calling the reader.
- If constructing a File in tests or code, include actual PEM content so size > 0.
- Fall back to the paste-private-key textarea option instead of file upload.
Example fix
// before
const [file] = e.target.files;
await readGitHubPrivateKeyFile(file);
// after
const [file] = e.target.files;
if (file.size === 0) {
setError("That file is empty. Re-download your GitHub App private key (.pem).");
return;
}
await readGitHubPrivateKeyFile(file); Defensive patterns
Strategy: validation
Validate before calling
if (file.size === 0) { showError("That file is empty. Choose the private key downloaded from your GitHub App."); return; } Type guard
const isNonEmptyFile = (f: Pick<File, "size">): boolean => f.size > 0;
Try / catch
try {
const key = await readGitHubPrivateKeyFile(file);
} catch (err) {
if (err instanceof Error && err.message.includes("empty")) {
showError(err.message);
} else { throw err; }
} Prevention
- Check file.size before reading in the input onChange handler
- Re-download keys rather than keeping old copies
- Surface the paste-key option alongside file upload
- Validate selected file starts with '-----BEGIN' for early feedback
When it happens
Trigger: User selects a 0-byte file in the GitHub App setup file input (e.g. an interrupted download or an empty placeholder file); a programmatically constructed File/Blob with size 0 is passed to `privateKey` -> readGitHubPrivateKeyFile.
Common situations: Browser download of the GitHub App .pem was interrupted leaving a zero-byte file; user picked the wrong (empty) file in the picker; automated test passes `new File([], "key.pem")` which has size 0.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
- That file is too large. Choose a GitHub App private key…
- A full lowercase source SHA is required.
- A reusable lease cannot be replaced and reacquired in the…
- A reusable lease handoff requires an execution workspace…
- A safe, unique --revision is required
AI-assisted analysis of paperclipai/paperclip@3f1d897a7c (2026-09-18).
Data as JSON: /api/errors/c77adc3ff6c41271.
Report an issue: GitHub.
Appendix: source
Thrown at ui/src/pages/apps/chat/github-private-key-file.ts:23
return {
start() {
revision += 1;
return revision;
},
invalidate() {
revision += 1;
},
isCurrent(candidate: number) {
return candidate === revision;
},
};
}
export async function readGitHubPrivateKeyFile(
file: Pick<File, "size" | "text">,
): Promise<string> {
if (file.size === 0) {
throw new Error(
"That file is empty. Choose the private key downloaded from your GitHub App.",
);
}
if (file.size > GITHUB_PRIVATE_KEY_FILE_MAX_BYTES) {
throw new Error(
"That file is too large. Choose a GitHub App private key smaller than 64 KB.",
);
}
let value: string;
try {
value = await file.text();
} catch {
throw new Error(
"Paperclip couldn't read that file. Choose the .pem file again or paste the private key.",
);
}
if (!value.trim()) {View on GitHub (pinned to 3f1d897a7c)