langgenius/dify · error · BadRequest
Invalid partner_key
Error message
Invalid partner_key
What it means
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).
Source
Thrown at api/controllers/console/billing/billing.py:96
class PartnerTenants(Resource):
@console_ns.doc("sync_partner_tenants_bindings")
@console_ns.doc(description="Sync partner tenants bindings")
@console_ns.doc(params={"partner_key": "Partner key"})
@console_ns.expect(console_ns.models[PartnerTenantsPayload.__name__])
@console_ns.response(200, "Tenants synced to partner successfully", console_ns.models[BillingResponse.__name__])
@console_ns.response(400, "Invalid partner information")
@setup_required
@login_required
@account_initialization_required
@only_edition_cloud
@with_current_user
@model_validate(PartnerTenantsPayload)
def put(self, req_data: PartnerTenantsPayload, current_user: Account, partner_key: str):
try:
click_id = req_data.click_id
decoded_partner_key = base64.b64decode(partner_key).decode("utf-8")
except Exception:
raise BadRequest("Invalid partner_key")
if not click_id or not decoded_partner_key or not current_user.id:
raise BadRequest("Invalid partner information")
return BillingService.sync_partner_tenants_bindings(current_user.id, decoded_partner_key, click_id)
View on GitHub (pinned to ef8544b173)
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.
Example fix
// before
try:
click_id = req_data.click_id
decoded_partner_key = base64.b64decode(partner_key).decode("utf-8")
except Exception:
raise BadRequest("Invalid partner_key")
// after
import binascii
try:
click_id = req_data.click_id
decoded_partner_key = base64.b64decode(partner_key, validate=True).decode("utf-8")
except (binascii.Error, UnicodeDecodeError, ValueError):
raise BadRequest("Invalid partner_key") Defensive patterns
Strategy: validation
Validate before calling
// Pre-validate partner_key is base64 and decodes to UTF-8 before the PUT.
function decodePartnerKey(key: string): string {
const decoded = atob(key);
if (!decoded) throw new Error('partner_key decodes to empty');
return decoded;
}
const decoded = decodePartnerKey(partnerKey); Type guard
function isBase64(s: string): boolean {
return /^[A-Za-z0-9+/_-]+={0,2}$/.test(s) && (() => { try { atob(s); return true; } catch { return false; } })();
} Try / catch
try {
await putPartnerTenants(partnerKey, clickId);
} catch (e) {
if (/Invalid partner_key/i.test(e.message)) { refreshPartnerKey(); } else throw e;
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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'.
Related errors
- Invalid partner information
- This email account has been deleted within the past 30 days
- provider_quota_exceeded
- model_currently_not_support
- account_in_freeze
AI-assisted analysis of langgenius/dify@ef8544b173 (2026-08-12).
Data as JSON: /api/errors/926655d9c56a0e4c.
Report an issue: GitHub.