{"record":{"id":"926655d9c56a0e4c","repo":"langgenius/dify","slug":"invalid-partner-key","errorCode":null,"errorMessage":"Invalid partner_key","messagePattern":"Invalid partner_key","errorType":"http","errorClass":"BadRequest","httpStatus":400,"severity":"error","filePath":"api/controllers/console/billing/billing.py","lineNumber":96,"sourceCode":"class PartnerTenants(Resource):\n    @console_ns.doc(\"sync_partner_tenants_bindings\")\n    @console_ns.doc(description=\"Sync partner tenants bindings\")\n    @console_ns.doc(params={\"partner_key\": \"Partner key\"})\n    @console_ns.expect(console_ns.models[PartnerTenantsPayload.__name__])\n    @console_ns.response(200, \"Tenants synced to partner successfully\", console_ns.models[BillingResponse.__name__])\n    @console_ns.response(400, \"Invalid partner information\")\n    @setup_required\n    @login_required\n    @account_initialization_required\n    @only_edition_cloud\n    @with_current_user\n    @model_validate(PartnerTenantsPayload)\n    def put(self, req_data: PartnerTenantsPayload, current_user: Account, partner_key: str):\n        try:\n            click_id = req_data.click_id\n            decoded_partner_key = base64.b64decode(partner_key).decode(\"utf-8\")\n        except Exception:\n            raise BadRequest(\"Invalid partner_key\")\n\n        if not click_id or not decoded_partner_key or not current_user.id:\n            raise BadRequest(\"Invalid partner information\")\n\n        return BillingService.sync_partner_tenants_bindings(current_user.id, decoded_partner_key, click_id)\n","sourceCodeStart":78,"sourceCodeEnd":102,"githubUrl":"https://github.com/langgenius/dify/blob/ef8544b173fd6cd7a8e71df2cab576e52bebbfbc/api/controllers/console/billing/billing.py#L78-L102","documentation":"Flask BadRequest (HTTP 400) raised at billing.py:96 in the partner-tenants PUT handler when base64.b64decode(partner_key).decode('utf-8') throws (or req_data.click_id access throws) inside the try block. partner_key is the URL path parameter; if it is not valid base64 or not valid UTF-8 after decoding, the broad `except Exception` fires and reports 'Invalid partner_key'. The endpoint is Cloud-only (@only_edition_cloud).","triggerScenarios":"PUT /console/api/billing/partner/tenants/<partner_key> on Cloud edition with a partner_key that is malformed base64, truncated, URL-mangled, or contains non-UTF-8 bytes. Any exception in the try (including a model field access error) maps to this message.","commonSituations":"Partner integration sends a raw key instead of its base64 encoding; URL-encoding double-escapes the key; or a stale/rotated partner key that no longer decodes. The broad `except Exception` also hides unexpected bugs as 'Invalid partner_key'.","solutions":["Send the partner_key exactly as issued, as standard base64, URL-safe in the path (encode any '+/=' appropriately).","Verify the key decodes to UTF-8 before sending: `base64.b64decode(key).decode('utf-8')` should succeed locally.","If the key was rotated, obtain the new partner_key from billing/partner admin.","Narrow the except clause (catch binascii.Error / UnicodeDecodeError specifically) so unrelated bugs are not masked."],"exampleFix":"// before\ntry:\n    click_id = req_data.click_id\n    decoded_partner_key = base64.b64decode(partner_key).decode(\"utf-8\")\nexcept Exception:\n    raise BadRequest(\"Invalid partner_key\")\n// after\nimport binascii\ntry:\n    click_id = req_data.click_id\n    decoded_partner_key = base64.b64decode(partner_key, validate=True).decode(\"utf-8\")\nexcept (binascii.Error, UnicodeDecodeError, ValueError):\n    raise BadRequest(\"Invalid partner_key\")","handlingStrategy":"validation","validationCode":"// Pre-validate partner_key is base64 and decodes to UTF-8 before the PUT.\nfunction decodePartnerKey(key: string): string {\n  const decoded = atob(key);\n  if (!decoded) throw new Error('partner_key decodes to empty');\n  return decoded;\n}\nconst decoded = decodePartnerKey(partnerKey);","typeGuard":"function isBase64(s: string): boolean {\n  return /^[A-Za-z0-9+/_-]+={0,2}$/.test(s) && (() => { try { atob(s); return true; } catch { return false; } })();\n}","tryCatchPattern":"try {\n  await putPartnerTenants(partnerKey, clickId);\n} catch (e) {\n  if (/Invalid partner_key/i.test(e.message)) { refreshPartnerKey(); } else throw e;\n}","preventionTips":["Send the partner_key exactly as issued (standard base64).","URL-encode the path segment to avoid '+/=' mangling.","Server-side: narrow the except to binascii.Error/UnicodeDecodeError to avoid masking real bugs."],"tags":["billing","partner","base64","cloud-edition","request-validation"],"backgroundTag":null,"analyzedSha":"ef8544b173fd6cd7a8e71df2cab576e52bebbfbc","analyzedAt":"2026-08-12T05:15:17.394Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}