jackwener/OpenCLI · error · CliError
API_ERROR
API_ERROR
Error message
toErrorMessage(payload, fallback)
What it means
ensureApiSuccess() validates that a JSON response payload from paperreview.ai has success === true. If the payload is missing, not an object, or has success !== true, it throws API_ERROR with the message derived from the payload (detail/message/error field, text) or the fallback. This is the application-level success check, distinct from HTTP status checks.
Source
Thrown at clis/paperreview/utils.js:120
if (rawText) {
try {
payload = JSON.parse(rawText);
}
catch {
payload = rawText;
}
}
return { response, payload };
}
export function ensureSuccess(response, payload, fallback, hint) {
if (!response.ok) {
const code = response.status === 404 ? 'NOT_FOUND' : 'API_ERROR';
throw new CliError(code, toErrorMessage(payload, fallback), hint);
}
}
export function ensureApiSuccess(payload, fallback, hint) {
if (!payload || typeof payload !== 'object' || payload.success !== true) {
throw new CliError('API_ERROR', toErrorMessage(payload, fallback), hint);
}
}
export function createUploadForm(urlData, pdfFile) {
const form = new FormData();
for (const [key, value] of Object.entries(urlData.presigned_fields ?? {})) {
form.append(key, value);
}
form.append('file', new Blob([new Uint8Array(pdfFile.buffer)], { type: 'application/pdf' }), pdfFile.fileName);
return form;
}
export async function uploadPresignedPdf(presignedUrl, pdfFile, urlData) {
let response;
try {
response = await fetch(presignedUrl, {
method: 'POST',
body: createUploadForm(urlData, pdfFile),
});
}View on GitHub (pinned to 49907e53dc)
Solutions
- Read the thrown message — it surfaces the server's detail/message/error explaining the rejection
- Confirm the request body/params are valid for the endpoint (e.g. correct s3Key, email format)
- Retry if the failure looks transient (quota, rate limits), otherwise fix the request
- Check for an API version change if the payload shape looks unfamiliar
Example fix
// before
ensureApiSuccess(payload, 'Submission failed'); // generic failure, cause unknown
// after
if (payload && typeof payload === 'object' && payload.success !== true) {
console.error('Server said:', payload.detail ?? payload.message ?? payload.error);
}
ensureApiSuccess(payload, 'Submission failed'); Defensive patterns
Strategy: type-guard
Validate before calling
function isApiSuccessPayload(payload) {
return payload !== null && typeof payload === 'object' && payload.success === true;
}
// run before relying on the response data (ensureApiSuccess does this check internally) Type guard
function isApiSuccessPayload(payload) {
return typeof payload === 'object' && payload !== null && 'success' in payload && payload.success === true;
} Try / catch
try {
ensureApiSuccess(payload, 'Submission failed');
} catch (e) {
if (e?.code === 'API_ERROR') {
const detail = payload && typeof payload === 'object' ? (payload.detail ?? payload.message ?? payload.error) : payload;
console.error('Server rejected the operation:', detail ?? e.message);
} else throw e;
} Prevention
- Always inspect the server's detail/message/error fields surfaced in the message
- Validate request bodies against the documented API schema
- Treat success:false as a business-rule rejection, not a transport bug
- Pin/monitor API versions; alert if payload shape changes
When it happens
Trigger: Calling an endpoint whose 200-OK JSON body contains success:false or an unexpected shape — e.g. the confirm/status endpoints returning { success: false, detail: '...' }, a non-JSON body parsed as a string, or an empty payload from an endpoint change.
Common situations: Server-side business-rule rejection despite HTTP 200 (e.g. invalid state, quota exhausted); API contract change where success field was renamed; the server returned an HTML error page captured as a plain string payload.
Related errors
- eastmoney convertible returned a malformed response envelope
- No user message found in request
- 获取到的视频播放信息对象不符合预期格式
- Bilibili view API returned a malformed ${label}
- Bilibili view API did not return pages[] for --page selectio
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/e0a67096eced689a.
Report an issue: GitHub.