{"record":{"id":"6db69741afb9984f","repo":"we-promise/sure","slug":"could-not-save-that-passkey-or-security-key-pleas","errorCode":null,"errorMessage":"Could not save that passkey or security key. Please try again.","messagePattern":"Could not save that passkey or security key\\. Please try again\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"app/javascript/controllers/webauthn_registration_controller.js","lineNumber":44,"sourceCode":"      const options = await this.fetchOptions();\n      const credential = await navigator.credentials.create({\n        publicKey: prepareCredentialCreationOptions(options),\n      });\n\n      await this.createCredential(serializePublicKeyCredential(credential));\n    } catch (error) {\n      this.showError(error.message);\n    }\n  }\n\n  async fetchOptions() {\n    const response = await fetch(this.optionsUrlValue, {\n      method: \"POST\",\n      headers: this.headers,\n      credentials: \"same-origin\",\n    });\n\n    if (!response.ok) throw new Error(await this.errorMessage(response));\n\n    return response.json();\n  }\n\n  async createCredential(credential) {\n    const response = await fetch(this.createUrlValue, {\n      method: \"POST\",\n      headers: this.headers,\n      credentials: \"same-origin\",\n      body: JSON.stringify({\n        credential,\n        webauthn_credential: {\n          nickname: this.hasNicknameTarget ? this.nicknameTarget.value : \"\",\n        },\n      }),\n    });\n\n    if (!response.ok) throw new Error(await this.errorMessage(response));","sourceCodeStart":26,"sourceCodeEnd":62,"githubUrl":"https://github.com/we-promise/sure/blob/e69894adb92547273377398c15f45c979cd9416a/app/javascript/controllers/webauthn_registration_controller.js#L26-L62","documentation":"Raised when JSON.parse of the Yahoo Finance HTTP body raises JSON::ParserError inside the chart-prices path (and identically for security info at app/models/provider/yahoo_finance.rb:283). The body was not valid JSON — typically an HTML error page (consent wall, CAPTCHA, 'Unable to process request'), an empty body from a proxy/429, or a gzipped/truncated response. The rescue re-wraps the parser message into the provider's generic Error, so the original body is lost unless logged before parsing.","triggerScenarios":"Yahoo responds with an HTML rate-limit/consent page instead of the v8 chart JSON; a CDN or corporate proxy strips the body or returns an error page; response body truncated (connection reset mid-transfer); stale crumb causing a redirect to an HTML login page that gets parsed as JSON.","commonSituations":"Scraping Yahoo from datacenter IPs that hit their consent/CAPTCHA wall; Faraday middleware misconfiguration (missing gzip decompression); running syncs through a proxy that injects an HTML block page; after Yahoo changes endpoint behavior the authenticated client follows a redirect chain ending in HTML.","solutions":["Log response.status and a truncated response.body before JSON.parse to see what Yahoo actually returned","On 429/backoff, retry with exponential backoff and throttle_request spacing honored","Refresh cookie/crumb (clear_crumb_cache + fetch_cookie_and_crumb) before retrying, since stale auth often yields HTML","Ensure Faraday adapter/middleware handles gzip and does not follow redirects to HTML error pages","If IP is Yahoo-blocked (datacenter range), route via a different provider or egress IP"],"exampleFix":"# before\ndata = JSON.parse(response.body)\n\n# after\nraise Error, \"Yahoo returned HTTP #{response.status} (non-JSON body)\" unless response.success?\ndata = begin\n  JSON.parse(response.body)\nrescue JSON::ParserError => e\n  Rails.logger.error(\"Non-JSON Yahoo body: #{response.body.to_s[0, 200]}\")\n  raise Error, \"Invalid response format: #{e.message}\"\nend","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"attempts = 0\nbegin\n  attempts += 1\n  prices = provider.fetch_security_prices(symbol: s, start_date: a, end_date: b)\nrescue Provider::YahooFinance::Error => e\n  raise unless e.message.start_with?(\"Invalid response format\") && attempts < 3\n  provider.send(:clear_crumb_cache) if provider.respond_to?(:clear_crumb_cache)\n  sleep(2**attempts)\n  retry\nend","preventionTips":["Check HTTP status and body prefix before JSON.parse in any custom provider code","Keep Yahoo request rates low (throttle) to avoid HTML rate-limit pages","Ensure Faraday handles gzip and doesn't follow redirects into HTML walls","Log raw body snippets on parse failure for postmortem"],"tags":["yahoo-finance","json","response-parsing","rate-limit","proxy"],"backgroundTag":"invalid-json-response","analyzedSha":"e69894adb92547273377398c15f45c979cd9416a","analyzedAt":"2026-08-21T18:22:41.165Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}