{"record":{"id":"9d74bc20b59dcb32","repo":"gitroomhq/postiz-app","slug":"http-error-status-response-status","errorCode":null,"errorMessage":"HTTP error! status: ${response.status}","messagePattern":"HTTP error! status: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"libraries/nestjs-libraries/src/short-linking/providers/kutt.ts","lineNumber":28,"sourceCode":"  },\n});\n\nexport class Kutt implements ShortLinking {\n  shortLinkDomain = KUTT_SHORT_LINK_DOMAIN;\n\n  async linksStatistics(links: string[]) {\n    return Promise.all(\n      links.map(async (link) => {\n        const linkId = link.split('/').pop();\n        \n        try {\n          const response = await fetch(\n            `${KUTT_API_ENDPOINT}/links/${linkId}/stats`,\n            getOptions()\n          );\n          \n          if (!response.ok) {\n            throw new Error(`HTTP error! status: ${response.status}`);\n          }\n          \n          const data = await response.json();\n          \n          return {\n            short: link,\n            original: data.address || '',\n            clicks: data.lastDay?.stats?.reduce((total: number, stat: any) => total + stat, 0)?.toString() || '0',\n          };\n        } catch (error) {\n          return {\n            short: link,\n            original: '',\n            clicks: '0',\n          };\n        }\n      })\n    );","sourceCodeStart":10,"sourceCodeEnd":46,"githubUrl":"https://github.com/gitroomhq/postiz-app/blob/0f1647f7491a217d43eb5ae7a480484bdf0aff3e/libraries/nestjs-libraries/src/short-linking/providers/kutt.ts#L10-L46","documentation":"Thrown by the Kutt short-link provider when the Kutt server's GET /links/{id}/stats endpoint returns a non-2xx status (e.g. 401 for a bad API key, 404 for an unknown link id). The code checks response.ok and throws a generic HTTP error with the status code embedded. Inside linksStatistics this is caught and the link is reported with 0 clicks, but the raw error surfaces anywhere the throw escapes.","triggerScenarios":"Calling linksStatistics(['https://kutt.it/abc123']) with a missing/invalid KUTT_API_KEY (401), a link id that does not exist in the Kutt account (404), or a wrong/unreachable KUTT_API_ENDPOINT (404/5xx from a proxy).","commonSituations":"KUTT_API_KEY env var not set (it is passed raw from process.env with no validation), self-hosting Kutt at a custom KUTT_API_ENDPOINT that is down or misrouted, links created under a different Kutt account/domain than the configured key.","solutions":["Verify KUTT_API_KEY and KUTT_API_ENDPOINT env vars are set and the key belongs to the same Kutt instance that created the short links","Test the key directly: curl -H 'X-API-Key: $KUTT_API_KEY' $KUTT_API_ENDPOINT/links/<id>/stats and confirm 200","If a 404, confirm the link id (last path segment) actually exists in that Kutt account","Add retry/backoff for transient 5xx from the Kutt server"],"exampleFix":"// before\nif (!response.ok) {\n  throw new Error(`HTTP error! status: ${response.status}`);\n}\n\n// after (actionable status info)\nif (!response.ok) {\n  throw new Error(`Kutt stats request failed for ${linkId}: ${response.status} ${response.statusText}`);\n}","handlingStrategy":"fallback","validationCode":"import { isSafePublicHttpsUrl } from './url.util';\n\nasync function canFetchKuttStats(link: string, apiKey?: string): Promise<boolean> {\n  if (!apiKey) return false; // avoid guaranteed 401\n  try { return isSafePublicHttpsUrl(link); } catch { return false; }\n}","typeGuard":"function isKuttLink(v: string): boolean {\n  return /^https:\\/\\/[\\w.-]+\\/([\\w-]+)$/.test(v);\n}","tryCatchPattern":"// linksStatistics already degrades to { clicks: '0' } per-link on failure;\n// mirror that at call sites:\ntry {\n  const stats = await kutt.linksStatistics(links);\n} catch {\n  const stats = links.map((l) => ({ short: l, original: '', clicks: '0' }));\n}","preventionTips":["Set KUTT_API_KEY and KUTT_API_ENDPOINT in every environment before enabling short-link analytics","Treat per-link stats as best-effort: never let a stats failure break the posting flow"],"tags":["kutt","http","short-link","api-key","statistics"],"backgroundTag":"http-error-status","analyzedSha":"0f1647f7491a217d43eb5ae7a480484bdf0aff3e","analyzedAt":"2026-08-27T12:09:55.020Z","schemaVersion":2},"datasetVersion":"2026-08-27T13:17:12.746Z"}