larksuite/cli · error
app registration returned credentials with a contradictory t
Error message
app registration returned credentials with a contradictory tenant brand %q
What it means
Thrown by RegisterAppWithDiscovery at internal/auth/app_registration.go:289 when a poll returns complete credentials (client_id + client_secret) whose user_info.tenant_brand parses to a brand different from the domain that actually issued them (effectiveBrand). The library treats the issuing domain as authoritative, so a contradicting final tenant report is a server protocol violation and registration aborts instead of silently overriding the brand.
Source
Thrown at internal/auth/app_registration.go:289
errStr := getStr(data, "error")
if errStr == "" {
result := &AppRegistrationResult{
ClientID: getStr(data, "client_id"),
ClientSecret: getStr(data, "client_secret"),
}
if userInfoRaw, ok := data["user_info"].(map[string]interface{}); ok {
result.UserInfo = &AppRegUserInfo{
OpenID: getStr(userInfoRaw, "open_id"),
TenantBrand: getStr(userInfoRaw, "tenant_brand"),
}
}
if result.ClientID != "" && result.ClientSecret != "" {
// The issuing domain is authoritative; a contradictory final
// tenant report is a protocol violation, not a brand override.
if result.UserInfo != nil && result.UserInfo.TenantBrand != "" &&
core.ParseBrand(result.UserInfo.TenantBrand) != effectiveBrand {
return nil, effectiveBrand, fmt.Errorf("app registration returned credentials with a contradictory tenant brand %q", result.UserInfo.TenantBrand)
}
return result, effectiveBrand, nil
}
// Incomplete credentials without an error: keep polling.
continue
}
switch errStr {
case "authorization_pending":
continue
case "slow_down":
interval = minInt(interval+5, maxPollIntervalSeconds)
fmt.Fprintf(errOut, "[lark-cli] app-registration: slow_down, interval increased to %ds\n", interval)
continue
case "access_denied":
return nil, effectiveBrand, ErrRegistrationDenied
case "expired_token", "invalid_grant":
return nil, effectiveBrand, ErrRegistrationExpiredView on GitHub (pinned to 7fd6ef3c07)
Solutions
- Restart the registration flow — a transient race may resolve on the next run.
- Ensure the account you approve in the browser belongs to the brand matching your region (Feishu vs Lark); approve with the correct account/tenant.
- Update the CLI and retry in case the server bug was fixed; check for known issues.
- If reproducible with a specific tenant, report the tenant_brand/issuing-domain pair to the service maintainers — this indicates a server protocol violation.
Defensive patterns
Strategy: try-catch
Type guard
func tenantBrandMatches(brand core.LarkBrand, ui *AppRegUserInfo) bool {
return ui == nil || ui.TenantBrand == "" || core.ParseBrand(ui.TenantBrand) == brand
} Try / catch
result, brand, err := RegisterAppWithDiscovery(ctx, client, resp, errOut)
if err != nil {
if strings.Contains(err.Error(), "contradictory tenant brand") {
// protocol violation: restart the flow and approve with the brand-correct account
}
return err
} Prevention
- Approve registration in the browser with an account whose tenant matches your regional brand.
- Avoid tenant brand migrations during an active registration.
- Keep the CLI and server protocol versions aligned; report reproducible mismatches.
When it happens
Trigger: Server returns credentials on domain A (e.g. feishu) while the final user_info.tenant_brand says brand B (e.g. lark), after the one permitted cross-brand switch already happened (switched=true prevents further switches but a later contradictory report still triggers this).
Common situations: User belongs to a tenant on the opposite brand from the polled domain at the exact moment credentials are issued; server-side brand-propagation race; tenant migrated brands mid-registration; backend bug emitting a stale tenant_brand in the final successful poll.
Related errors
- app registration failed: response missing device_code
- protocol: frame exceeds MaxFrameBytes
- app registration failed: read body: %w
- app registration failed: HTTP %d – response not JSON
- app registration failed: %s
AI-assisted analysis of larksuite/cli@7fd6ef3c07 (2026-09-04).
Data as JSON: /api/errors/da87ba568a75bc82.
Report an issue: GitHub.