antiwork/gumroad · error · ResponseError
Failed to archive product
Error message
Failed to archive product
What it means
ResponseError('Failed to archive product') thrown at product_dashboard.ts:25 when the POST to Routes.products_archived_index_path(id: permalink) answers { success: false } with an empty or missing `error` field — the literal string is the fallback after `json.error ||`. So the server did refuse the archive, but its payload omitted the reason, and the user sees the generic fallback.
Source
Thrown at app/javascript/data/product_dashboard.ts:25
method: "DELETE",
url: Routes.link_path(permalink),
accept: "json",
});
const json = typia.assert<{ success: true } | { success: false; message: string }>(await response.json());
if (!json.success) throw new ResponseError(json.message);
}
export async function archiveProduct(permalink: string) {
const response = await request({
url: Routes.products_archived_index_path(),
method: "POST",
accept: "json",
data: { id: permalink },
});
const json = typia.assert<{ success: true } | { success: false; error: string }>(await response.json());
if (!json.success) throw new ResponseError(json.error || "Failed to archive product");
}
export async function unarchiveProduct(permalink: string) {
const response = await request({
url: Routes.products_archived_path(permalink),
method: "DELETE",
accept: "json",
});
const json = typia.assert<{ success: true; archived_products_count: number } | { success: false; errors: string[] }>(
await response.json(),
);
if (!json.success) throw new ResponseError(json.errors[0] || "Failed to unarchive product");
return json.archived_products_count;
}
export async function duplicateProduct(permalink: string, productName: string) {
const response = await request({View on GitHub (pinned to afeacbd394)
Solutions
- Reproduce with DevTools open and inspect the products/archived POST response body to see the real (empty-field) payload and status
- Check server logs for the archive guard that returned success:false — the reason lives there, not in the response
- Fix the endpoint to always populate `error` when returning success:false (see exampleFix) so clients can surface the true cause
- If the payload shape was renamed, align the typia assert on the actual envelope to catch drift via TypeError instead of silent fallback
Example fix
# app/controllers/products/archived_controller.rb (server side)
# before
render json: { success: false } # guard failed, no reason
# after
render json: { success: false, error: 'Product cannot be archived while linked to an active bundle' } Defensive patterns
Strategy: try-catch
Type guard
import { assertResponseError } from '$app/utils/request';
assertResponseError(e); Try / catch
try {
await archiveProduct(permalink);
} catch (e) {
assertResponseError(e);
// generic fallback text means the server sent an empty `error` — check logs, then resync
if (e.message === 'Failed to archive product') logEmptyArchiveError(permalink);
showError(e.message);
} Prevention
- Treat the literal 'Failed to archive product' string as a server payload bug and file it — the refusal reason was dropped server-side
- Assert on the response envelope in endpoint tests so success:false with an empty error fails CI
- Resync the archived list after any archive attempt
When it happens
Trigger: The archive endpoint returns success:false with error: '' (or the key absent): server-side guard rejected archiving (product state, permissions, dependent records) while the controller failed to populate the error field.
Common situations: Backend refactor changes the refusal payload from {error: '...'} to {errors: [...]} or {message: '...'} leaving `error` undefined; archiving a product already archived; archiving products owned by another account from a shared dashboard; the empty-field case making support tickets hard to diagnose because every user report says only 'Failed to archive product'.
Related errors
- Failed to unarchive product
- json.message
- json.error_message
- responseData.error_message
- Sorry, failed to duplicate '${productName}': ${json.error_me
AI-assisted analysis of antiwork/gumroad@afeacbd394 (2026-08-21).
Data as JSON: /api/errors/c78b872a90cb9cb7.
Report an issue: GitHub.