{"record":{"id":"a113fc87a0ea89ce","repo":"we-promise/sure","slug":"brexitem-accountflow-noapitokenerror","errorCode":null,"errorMessage":"BrexItem::AccountFlow::NoApiTokenError","messagePattern":"BrexItem::AccountFlow::NoApiTokenError","errorType":"exception","errorClass":"BrexItem::AccountFlow::NoApiTokenError","httpStatus":null,"severity":"warning","filePath":"app/models/brex_item/account_flow.rb","lineNumber":370,"sourceCode":"            names: result.already_linked_names.join(\", \")\n          )\n        )\n      else\n        navigation(:new_account, :alert, I18n.t(\"brex_items.link_accounts.link_failed\"))\n      end\n    end\n\n    def navigation(target, flash_type, message)\n      NavigationResult.new(target: target, flash_type: flash_type, message: message)\n    end\n\n    def cache_key\n      self.class.cache_key(family, brex_item)\n    end\n\n    def fetch_accounts\n      provider = brex_item&.brex_provider\n      raise NoApiTokenError unless provider.present?\n\n      accounts_data = provider.get_accounts\n      accounts_data[:accounts] || []\n    end\n\n    def accounts\n      cached_accounts = Rails.cache.read(cache_key)\n      return cached_accounts unless cached_accounts.nil?\n\n      fetch_and_cache_accounts\n    end\n\n    def fetch_and_cache_accounts\n      available_accounts = fetch_accounts\n      Rails.cache.write(cache_key, available_accounts, expires_in: CACHE_TTL)\n      available_accounts\n    end\n","sourceCodeStart":352,"sourceCodeEnd":388,"githubUrl":"https://github.com/we-promise/sure/blob/e69894adb92547273377398c15f45c979cd9416a/app/models/brex_item/account_flow.rb#L352-L388","documentation":"Raised by BrexItem::AccountFlow#fetch_accounts as NoApiTokenError when brex_item.brex_provider is nil — no API token configured on the selected Brex connection, or no brex_item resolved at all (brex_item nil makes brex_item&.brex_provider nil too). Every public flow method (preload_payload, link_*, select_*) rescues it and converts it into a no_api_token state or navigation alert rather than letting it bubble.","triggerScenarios":"A user opens the Brex account flow before entering/storing their API token (brex_item.credentials_configured? false, see account_flow.rb:73), the token was blanked by an edit, or the flow was constructed with a brex_item_id that resolves to a deleted/missing item — then fetch_accounts hits `raise NoApiTokenError unless provider.present?` at app/models/brex_item/account_flow.rb:368-370.","commonSituations":"Bookmark/deep-link into the account picker before setup completes; settings form saved with empty token field; multi-connection families where the referenced item lost its credentials; tests instantiating AccountFlow on an item without a token.","solutions":["Complete token setup first: save the Brex API token on the BrexItem (settings → providers), then re-enter the flow.","Guard the controller action: redirect unless brex_item&.credentials_configured? before rendering any flow that fetches accounts.","Call the result-object wrappers (preload_payload / select_accounts_result / link_existing_account_result) instead of the bang internals — they translate NoApiTokenError into a structured no_api_token result.","Expire the accounts cache (Rails.cache.delete(BrexItem::AccountFlow.cache_key(family, brex_item))) after changing the token so stale state does not mask the fix."],"exampleFix":"# before\nflow = BrexItem::AccountFlow.new(family: family, brex_item_id: params[:brex_item_id])\nflow.preload_payload\n\n# after — gate on credentials before any fetch\nflow = BrexItem::AccountFlow.new(family: family, brex_item_id: params[:brex_item_id])\nunless flow.selected? && flow.brex_item.credentials_configured?\n  return redirect_to settings_providers_path, alert: \"Connect your Brex account token first.\"\nend\nresult = flow.preload_payload # => { success: false, error: \"no_api_token\", ... } if token missing","handlingStrategy":"validation","validationCode":"flow = BrexItem::AccountFlow.new(family: family, brex_item_id: params[:brex_item_id])\nreturn redirect_to(settings_providers_path, alert: \"Add your Brex API token first\") unless flow.selected? && flow.brex_item.credentials_configured?","typeGuard":"# Ruby\ndef brex_flow_ready?(flow)\n  flow.selected? && flow.brex_item.respond_to?(:credentials_configured?) && flow.brex_item.credentials_configured?\nend","tryCatchPattern":null,"preventionTips":["Gate every Brex flow screen on brex_item.credentials_configured? before fetching accounts.","Prefer the result-object APIs (preload_payload, select_accounts_result, link_existing_account_result) — they translate NoApiTokenError into structured no_api_token states.","Expire the accounts cache after saving a new token so the next fetch proves the credential works."],"tags":["brex","credentials","configuration","account-linking"],"backgroundTag":"missing-api-token","analyzedSha":"e69894adb92547273377398c15f45c979cd9416a","analyzedAt":"2026-08-21T18:22:41.165Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}