{"record":{"id":"e180a24303f9ce82","repo":"iflytek/astron-agent","slug":"tenant-id-must-remain-s-because-persisted-bootstrap-data","errorCode":null,"errorMessage":"TENANT_ID must remain %s because persisted bootstrap data refers to it","messagePattern":"TENANT_ID must remain (.+?) because persisted bootstrap data refers to it","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/tenant/config/bootstrap_credentials.go","lineNumber":64,"sourceCode":"\t\treturn TenantBootstrapCredentials{}, err\n\t}\n\n\tcredentials := TenantBootstrapCredentials{\n\t\tTenantID: tenantID,\n\t\tAPIKey:   apiKey,\n\t\tSecret:   secret,\n\t}\n\tif err := credentials.Validate(); err != nil {\n\t\treturn TenantBootstrapCredentials{}, err\n\t}\n\treturn credentials, nil\n}\n\n// Validate enforces the storage and HTTP-header constraints shared by every\n// bootstrap credential consumer.\nfunc (credentials TenantBootstrapCredentials) Validate() error {\n\tif credentials.TenantID != BootstrapTenantID {\n\t\treturn fmt.Errorf(\n\t\t\t\"TENANT_ID must remain %s because persisted bootstrap data refers to it\",\n\t\t\tBootstrapTenantID,\n\t\t)\n\t}\n\tif err := validateCredential(\"TENANT_KEY\", credentials.APIKey); err != nil {\n\t\treturn err\n\t}\n\tif err := validateCredential(\"TENANT_SECRET\", credentials.Secret); err != nil {\n\t\treturn err\n\t}\n\tif credentials.APIKey == credentials.Secret {\n\t\treturn errors.New(\"TENANT_KEY and TENANT_SECRET must be distinct values\")\n\t}\n\tif credentials.APIKey == LegacyTenantKey || credentials.Secret == LegacyTenantSecret {\n\t\treturn errors.New(\"published legacy tenant credentials cannot be used\")\n\t}\n\treturn nil\n}","sourceCodeStart":46,"sourceCodeEnd":82,"githubUrl":"https://github.com/iflytek/astron-agent/blob/5e758547a83371a5a4b29dadf4ac03e8dd527635/core/tenant/config/bootstrap_credentials.go#L46-L82","documentation":"TenantBootstrapCredentials.Validate enforces that TenantID equals the hard-coded BootstrapTenantID (\"680ab54f\"), because persisted bootstrap data in MySQL references that tenant ID. Setting any other TENANT_ID would orphan existing bootstrap rows, so Validate deliberately rejects it with this message.","triggerScenarios":"LoadTenantBootstrapCredentials or reconcileTenantBootstrap(Transaction) or parseMysqlConfig calls Validate with credentials.TenantID != \"680ab54f\" — e.g. the TENANT_ID env var is set to a custom value (even after trimming whitespace).","commonSituations":"Operator sets TENANT_ID to their own tenant identifier assuming it is configurable; multi-tenant deployments reuse a shared manifest with a different TENANT_ID; a stale env var from another environment leaks into the tenant service.","solutions":["Remove the TENANT_ID environment variable so LoadTenantBootstrapCredentials defaults it to BootstrapTenantID (\"680ab54f\").","If it must be set explicitly, set it to exactly \"680ab54f\".","Do not attempt to change BootstrapTenantID unless you also migrate persisted bootstrap data referencing the old ID.","Search deployment manifests (Helm values, docker-compose, k8s Secrets) for TENANT_ID and align them."],"exampleFix":"// before (env)\nTENANT_ID=my-custom-tenant\n\n// after\n# TENANT_ID removed; defaults to 680ab54f","handlingStrategy":"validation","validationCode":"const BootstrapTenantID = \"680ab54f\"\nif v := os.Getenv(\"TENANT_ID\"); v != \"\" && v != BootstrapTenantID {\n\tlog.Fatalf(\"TENANT_ID must be %s or unset\", BootstrapTenantID)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never set TENANT_ID in deployment manifests; rely on the default.","Grep manifests for TENANT_ID in CI to catch accidental overrides.","Treat BootstrapTenantID as immutable infrastructure, like a database name."],"tags":["config","credentials","validation","go"],"backgroundTag":"invalid-config-value","analyzedSha":"5e758547a83371a5a4b29dadf4ac03e8dd527635","analyzedAt":"2026-09-12T08:03:51.356Z","contentChangedAt":"2026-09-12T08:03:51.356Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}