{"record":{"id":"b68014878d55e7cc","repo":"antiwork/gumroad","slug":"something-went-wrong-b68014","errorCode":null,"errorMessage":"Something went wrong.","messagePattern":"Something went wrong\\.","errorType":"exception","errorClass":"ResponseError","httpStatus":null,"severity":"warning","filePath":"app/javascript/data/discover.ts","lineNumber":20,"sourceCode":"\nexport type AutocompleteSearchResults = {\n  products: {\n    name: string;\n    url: string;\n    seller_name: string | null;\n    thumbnail_url: string | null;\n  }[];\n  recent_searches: string[];\n  viewed?: boolean;\n};\n\nexport async function deleteAutocompleteSearch(data: { query: string }) {\n  const response = await request({\n    method: \"DELETE\",\n    accept: \"json\",\n    url: Routes.discover_search_autocomplete_path(data),\n  });\n  if (!response.ok) throw new ResponseError();\n}\n","sourceCodeStart":2,"sourceCodeEnd":22,"githubUrl":"https://github.com/antiwork/gumroad/blob/afeacbd394069a1cbf0c6c50ee8e900925050370/app/javascript/data/discover.ts#L2-L22","documentation":"deleteAutocompleteSearch() throws at line 20 when DELETE discover_search_autocomplete_path(data) returns 4xx — removing one entry from the signed-in user's Discover recent searches. The whole data object is passed as route params, so a blank/absent query produces a route the router will not match or the controller rejects; expired sessions (401) and CSRF failures on DELETE also land here. Impact is cosmetic — a suggestion entry — so warning severity.","triggerScenarios":"query empty or whitespace so route generation fails (404/422); session expired so no recent-search store exists (401); DELETE sent without a valid CSRF token; duplicate deletes racing the first (404).","commonSituations":"A 'clear' UI firing one DELETE per entry while the user navigates away; test harness without cookies; stale state submitting the empty search box.","solutions":["Trim and require a non-empty query before firing the request","Treat failure as non-fatal: remove the entry locally — the server list reconverges on next page load","If entries keep reappearing, check DevTools: the DELETEs are 401/404, not succeeding","Re-login when every authenticated call on the page fails"],"exampleFix":"// before\ndeleteAutocompleteSearch({ query }).catch(() => {});\n\n// after\nif (!query.trim()) return;\nsetRecentSearches((prev) => prev.filter((q) => q !== query)); // optimistic\ndeleteAutocompleteSearch({ query: query.trim() }).catch(() => {/* self-heals on next load */});","handlingStrategy":"fallback","validationCode":"const q = query.trim();\nif (!q) return; // empty query cannot match the route — skip the request entirely","typeGuard":"const isResponseError = (e: unknown): e is ResponseError => e instanceof ResponseError;","tryCatchPattern":"setRecentSearches((prev) => prev.filter((s) => s !== query)); // optimistic update first\ndeleteAutocompleteSearch({ query: query.trim() }).catch(() => {\n  // non-fatal: server history reconverges on next page load\n});","preventionTips":["Never fire the DELETE with an empty or whitespace query — route generation will not match","Update local state first and treat server failure as cosmetic drift","Do not build error UI for this call; log quietly if entries reappear persistently","Re-login when every authenticated request on the page starts failing"],"tags":["gumroad","discover","search-history","fetch","http-4xx","typescript"],"backgroundTag":"http-4xx-client-error","analyzedSha":"afeacbd394069a1cbf0c6c50ee8e900925050370","analyzedAt":"2026-08-21T17:58:52.159Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}