{"record":{"id":"e667682be62e2513","repo":"chatboxai/chatbox","slug":"failed-to-publish-to-vibedrop-status-status","errorCode":null,"errorMessage":"Failed to publish to VibeDrop (status ${status})","messagePattern":"Failed to publish to VibeDrop \\(status (.+?)\\)","errorType":"http","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/renderer/packages/vibedrop.ts","lineNumber":107,"sourceCode":"  const { html, vdKey, title, visibility, slug } = params\n  if (!html?.trim()) {\n    throw new Error('HTML content is empty, nothing to publish.')\n  }\n\n  const body: Record<string, unknown> = { html, visibility }\n  if (title) body.title = title\n  if (slug) body.slug = slug\n\n  const { status, json } = await postJson(`${VIBEDROP_API_ORIGIN}/v1/sites/inline`, body, vdKey)\n\n  if (status === 401 || status === 403) {\n    throw new VibedropAuthError(json?.error?.message || 'VibeDrop authorization failed')\n  }\n  if (status === 404 && json?.error?.code === 'slug_not_owned') {\n    throw new VibedropSlugNotOwnedError('slug no longer owned')\n  }\n  if (status >= 400 || !json?.site?.url) {\n    throw new Error(json?.error?.message || `Failed to publish to VibeDrop (status ${status})`)\n  }\n\n  return { slug: json.site.slug, url: json.site.url, visibility: json.site.visibility }\n}\n\n// ===== client-side caches (settings-persisted) =====\n\n// Decodes the email claim from the current account's JWT access token. Used to\n// bind the cached publish key to an account so it is never reused across\n// accounts (e.g. after switching login without an explicit logout).\nfunction currentAccountEmail(): string | null {\n  const token = authInfoStore.getState().accessToken\n  if (!token) return null\n  try {\n    const payload = token.split('.')[1]\n    if (!payload) return null\n    const json = JSON.parse(atob(payload.replace(/-/g, '+').replace(/_/g, '/')))\n    return typeof json.email === 'string' && json.email ? json.email.toLowerCase() : null","sourceCodeStart":89,"sourceCodeEnd":125,"githubUrl":"https://github.com/chatboxai/chatbox/blob/81571269addb6bafb589a920b2883f1e1e084fd1/src/renderer/packages/vibedrop.ts#L89-L125","documentation":"Thrown by publishToVibedrop() as the catch-all when the response status is >= 400 (after auth and slug cases are handled) OR when status is 2xx but json.site.url is missing. It is the generic VibeDrop publish failure, preferring the server's error.message and falling back to a status-coded string.","triggerScenarios":"postJson returns any status >= 400 not already handled (e.g. 400 validation, 429 rate limit, 500), or a successful status whose body lacks json.site.url. The guard `if (status >= 400 || !json?.site?.url) throw ...` fires.","commonSituations":"Validation errors (invalid visibility/title), rate limiting, server-side 5xx, malformed response shape after a backend change, partial outage returning 200 with empty body.","solutions":["Read the embedded server error.message — it usually states the specific validation/limit problem.","For 429, wait and retry with backoff.","For 5xx, retry after a short delay; if persistent, check VibeDrop status.","If the body shape is unexpected, confirm the VibeDrop API version matches the client."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"function looksPublishable(status: number, json: unknown): boolean {\n  return status < 400 && !!json && typeof (json as any)?.site?.url === 'string'\n}","typeGuard":"function isVibedropPublishSuccess(json: unknown): json is { site: { slug: string; url: string; visibility: string } } {\n  return !!json && typeof json === 'object' && typeof (json as any).site?.url === 'string'\n}","tryCatchPattern":"try {\n  await publishToVibedrop(params)\n} catch (e) {\n  if (e instanceof Error && /Failed to publish to VibeDrop/.test(e.message)) {\n    // inspect server message; retry with backoff for 429/5xx\n  }\n}","preventionTips":["Distinguish 429/5xx (retryable) from 4xx validation (fix input).","Read the embedded server error.message before retrying.","Confirm VibeDrop API version compatibility after backend changes."],"tags":["vibedrop","publish","http","fallback"],"backgroundTag":null,"analyzedSha":"81571269addb6bafb589a920b2883f1e1e084fd1","analyzedAt":"2026-08-12T21:51:44.981Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}