How to Debug Image Generation Failures and Handle Error Codes in awesome-gpt-image-2
To debug image generation failures in awesome-gpt-image-2, inspect the network response for the error and retryAfterMs fields, check server logs for the Apimart error code, and handle specific codes like APIMART_RATE_LIMITED (429) or APIMART_BALANCE_REQUIRED (500) by mapping them through the statusForError() function in api/generation/status.js.
The awesome-gpt-image-2 repository provides a robust image generation pipeline built on the Apimart API. When generation requests fail, the system returns structured error objects with custom codes that propagate from the backend client through to the frontend React components. Understanding how to debug these failures requires tracing the error flow through src/apimartClient.js, the API layer in api/generation/, and the UI components in src/image25/.
Understanding the Error Handling Architecture
The error handling flow follows a three-tier architecture that transforms raw HTTP errors into user-friendly messages.
The Apimart Client Layer
All image generation requests originate in src/apimartClient.js, which wraps the Apimart API. When a request fails, the client creates a domain-specific Error instance using the apimartErrorCode() helper function. This error object contains:
code: The specific error identifier (e.g.,APIMART_RATE_LIMITED)status: The HTTP status from the upstream responseretryAfterMs: Calculated delay before retrying rate-limited requestsupstreamMessage: Original error message from Apimart
API Layer Translation
Errors bubble up to the generation endpoints under api/generation/*. The api/generation/status.js file contains the critical statusForError() and publicStatusErrorCode() functions that map internal Apimart codes to appropriate HTTP status codes and public-facing error identifiers.
Frontend Consumption
React components in src/image25/**/*.jsx (notably App.jsx) consume these errors as JSON responses. When ok: false appears in the response payload, the UI displays contextual messages based on the error field and implements retry logic using the retryAfterMs value.
Key Error Codes and Their Meanings
The following error codes are defined implicitly within the Apimart client and mapped to HTTP statuses in the API layer:
APIMART_RATE_LIMITED: API quota exceeded; returns HTTP 429 withretryAfterMsAPIMART_INVALID_TASK: Malformed or expired generation task; returns HTTP 400APIMART_API_KEY_INVALID: Authentication failure; returns HTTP 500APIMART_BALANCE_REQUIRED: Insufficient account credits; returns HTTP 500APIMART_TASK_FAILED: Generic processing failure; returns HTTP 500APIMART_POLL_ABORTED: Client-side timeout waiting for completion; returns HTTP 503APIMART_GENERATION_FAILED: Fallback for unexpected errors; returns HTTP 500
Debugging Image Generation Failures Step by Step
When users report failed image generations, follow this systematic debugging workflow.
Inspect Network Responses
Open browser DevTools and examine the response body from /api/generation/* endpoints. A typical error response follows this structure:
{
"ok": false,
"error": "APIMART_RATE_LIMITED",
"retryAfterMs": 7000
}
The error field contains the machine-readable code, while retryAfterMs indicates when to retry rate-limited requests.
Check Server Logs
On the backend, errors are logged before being re-thrown to the API layer. Search logs for codes like APIMART_BALANCE_REQUIRED or APIMART_TASK_FAILED. The source of all errors is src/apimartClient.js, where the original Apimart payload is wrapped with additional metadata.
Validate Request Payloads
For errors like APIMART_REQUEST_REJECTED or APIMART_BALANCE_REQUIRED, verify the upstream payload fields. The upstreamMessage property in the error object captures the original Apimart error description, helping distinguish between content policy violations and payment issues.
Verify Retry Logic
When encountering APIMART_RATE_LIMITED, confirm that your frontend respects the retryAfterMs value. The reference implementation in src/image25/App.jsx schedules automatic retries using this delay. If the delay is excessive, check your Apimart account quota settings.
Handling Errors in the Frontend
Implement defensive polling logic that handles the specific error codes returned by the generation API.
async function pollGeneration(id) {
try {
const res = await fetch(`/api/generation/status?id=${id}`);
const data = await res.json();
if (!data.ok) {
switch (data.error) {
case 'APIMART_RATE_LIMITED':
console.warn(`Rate limited. Retrying in ${data.retryAfterMs}ms`);
setTimeout(() => pollGeneration(id), data.retryAfterMs);
break;
case 'APIMART_BALANCE_REQUIRED':
alert('Insufficient credits. Please top up your account.');
break;
case 'APIMART_INVALID_TASK':
alert('Invalid task ID or parameters.');
break;
default:
alert(`Generation failed: ${data.error}`);
}
return;
}
displayImage(data.imageUrl);
} catch (e) {
console.error('Network or unexpected error:', e);
}
}
This implementation handles rate limiting with automatic retry, displays user-friendly messages for balance issues, and provides fallback error handling for edge cases.
Server-Side Error Implementation
The backend constructs rich error objects that preserve context from the upstream API.
In src/apimartClient.js, errors are instantiated with full metadata:
if (!response.ok) {
const payload = await response.json();
const code = apimartErrorCode(response.status, payload);
const error = new Error(code);
error.code = error.message;
error.status = response.status;
error.retryAfterMs = retryAfterMilliseconds(
response.headers?.get?.('retry-after')
);
error.upstreamMessage = String(payload?.error?.message || '');
throw error;
}
The API layer then translates these internal errors in api/generation/status.js:
function statusForError(error) {
if (error?.code === 'APIMART_RATE_LIMITED') return 429;
if (error?.code === 'APIMART_INVALID_TASK') return 400;
if (error?.code === 'APIMART_API_KEY_INVALID' ||
error?.code === 'APIMART_BALANCE_REQUIRED') return 500;
return 500;
}
This mapping ensures that rate limits return proper 429 status codes for HTTP caching and retry-aware clients, while internal errors return 500 series codes.
Summary
- Trace errors through three layers: The Apimart client (
src/apimartClient.js), API endpoints (api/generation/status.js), and React frontend (src/image25/App.jsx). - Handle
APIMART_RATE_LIMITEDwith care: Respect theretryAfterMsfield to implement compliant backoff strategies. - Check
upstreamMessagefor root causes: This field contains the original Apimart error description for debugging authentication or balance issues. - Map internal codes to HTTP statuses: Use
statusForError()to return appropriate status codes (429 for rate limits, 400 for invalid tasks). - Log before throwing: Server logs in the client wrapper preserve the full error context before API layer transformation.
Frequently Asked Questions
What does the APIMART_RATE_LIMITED error code mean?
The APIMART_RATE_LIMITED code indicates that your request exceeded the Apimart API quota for your account. According to the source code in src/apimartClient.js, this error includes a retryAfterMs property calculated from the upstream Retry-After header. The API layer maps this to HTTP status 429, and the frontend should wait the specified milliseconds before retrying the request.
How do I distinguish between authentication errors and balance errors?
Both APIMART_API_KEY_INVALID and APIMART_BALANCE_REQUIRED return HTTP 500 status codes, but you can differentiate them by examining the upstreamMessage property in the error response. In src/apimartClient.js, this field is populated from payload?.error?.message, providing the specific reason from the Apimart API. Check your server logs for the exact code to determine whether to prompt users to check their API key or add credits.
Where should I implement custom error handling for the frontend?
Implement custom error handling in the polling functions within src/image25/App.jsx or similar React components. The reference implementation checks the ok boolean in the JSON response, then switches on the error string to display contextual UI messages. For rate limiting specifically, use the retryAfterMs value to schedule automatic retries via setTimeout() rather than alerting the user.
What if I receive an HTML error page instead of JSON?
If you receive a plain HTML error response instead of the expected JSON structure { ok: false, error: "..." }, the request likely failed before reaching the Apimart client middleware. This typically indicates a server configuration issue, routing error, or unhandled exception in the API layer outside of the generation endpoints. Check that your request reaches /api/generation/* endpoints and that the statusForError() function in api/generation/status.js is properly wrapping all thrown exceptions.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →