Stirling-Tools/Stirling-PDF · error · Error
Password removal did not produce a file.
Error message
Password removal did not produce a file.
What it means
Thrown in runAutomaticPasswordRemoval() when processResponse(response.data, [file]) returns an empty array — the server's /api/v1/security/remove-password endpoint returned a response, but no extractable File was produced from it. This typically means the server returned an error body (not a PDF blob) that processResponse could not interpret as a file. The message is i18n-localized via encryptedPdfUnlock.emptyResponse.
Source
Thrown at frontend/editor/src/core/contexts/FileContext.tsx:420
);
}
const params: RemovePasswordParameters = { password };
const formData = buildRemovePasswordFormData(params, file);
const response = await apiClient.post(
"/api/v1/security/remove-password",
formData,
{
responseType: "blob",
suppressErrorToast: true, // Handle errors in modal UI instead of toast
},
);
const responseFiles = await processResponse(response.data, [file]);
const unlockedFile = responseFiles[0];
if (!unlockedFile) {
throw new Error(
t(
"encryptedPdfUnlock.emptyResponse",
"Password removal did not produce a file.",
),
);
}
const processedMetadata =
await generateProcessedFileMetadata(unlockedFile);
const thumbnail = processedMetadata?.thumbnailUrl;
const operation: ToolOperation = {
toolId: "removePassword",
timestamp: Date.now(),
};
const childStub = createChildStub(
parentStub,View on GitHub (pinned to 9ef20dcab8)
Solutions
- Check response headers Content-Type before calling processResponse — if it's not application/pdf, parse as error JSON.
- Validate response.data.size > 0 (for blob responses) before processing.
- Inspect the raw response in the catch block to distinguish wrong-password from server errors.
- Add server-side validation to return proper HTTP error codes (401/403) for wrong passwords instead of 200 with error body.
Example fix
// before
const responseFiles = await processResponse(response.data, [file]);
const unlockedFile = responseFiles[0];
if (!unlockedFile) {
throw new Error(t("encryptedPdfUnlock.emptyResponse", "Password removal did not produce a file."));
}
// after
const contentType = response.headers?.["content-type"] ?? "";
if (!contentType.includes("application/pdf")) {
const errorText = await response.data.text();
throw new Error(`Server did not return a PDF: ${errorText.slice(0, 200)}`);
}
const responseFiles = await processResponse(response.data, [file]);
const unlockedFile = responseFiles[0];
if (!unlockedFile) {
throw new Error(t("encryptedPdfUnlock.emptyResponse", "Password removal did not produce a file."));
} Defensive patterns
Strategy: try-catch
Validate before calling
// Check Content-Type and blob size before processing
const contentType = response.headers?.['content-type'] ?? '';
if (!contentType.includes('application/pdf')) {
// Server returned an error body, not a PDF
const errorText = await (response.data as Blob).text();
throw new Error(`Password removal failed: ${errorText.slice(0, 200)}`);
}
if (response.data.size === 0) {
throw new Error('Server returned an empty response.');
} Type guard
function isPdfBlob(response: AxiosResponse): boolean {
const ct = response.headers?.['content-type'] ?? '';
return ct.includes('application/pdf') && response.data instanceof Blob && response.data.size > 0;
} Try / catch
try {
const response = await apiClient.post('/api/v1/security/remove-password', formData, {
responseType: 'blob',
suppressErrorToast: true,
});
if (!isPdfBlob(response)) {
const errorText = await response.data.text();
setModalError(`Server error: ${errorText.slice(0, 200)}`);
return;
}
// process the valid PDF
} catch (error) {
setModalError('Password removal failed. Please check the password and try again.');
} Prevention
- Check response Content-Type before assuming the blob is a PDF.
- Validate blob size > 0 before calling processResponse.
- Ensure the server returns proper HTTP error codes (401/403) for wrong passwords.
- Test with wrong passwords to verify the error path surfaces correctly in the modal.
When it happens
Trigger: The password was incorrect and the server returned an error JSON/HTML instead of a PDF blob, but with a 200 status. Or the server returned an empty response body. The suppressErrorToast flag means no toast was shown, so this throw is the only signal to the modal UI.
Common situations: Wrong password submitted (server returns error in body with 200). Server bug returning empty body. Response format change where processResponse no longer recognizes the content type.
Related errors
- The selected file is no longer available.
- Response is not a valid PDF. Header: "${head}"
- The server processed the request but returned no files.
- Unsupported unit: ${unit}
- Invalid real-world distance (must be positive)
AI-assisted analysis of Stirling-Tools/Stirling-PDF@9ef20dcab8 (2026-08-13).
Data as JSON: /api/errors/a384a0847c1c17ff.
Report an issue: GitHub.