{"record":{"id":"5b910b9b31b3521e","repo":"rancher/rancher","slug":"invalid-clientsecret","errorCode":null,"errorMessage":"invalid clientSecret","messagePattern":"invalid clientSecret","errorType":"http","errorClass":null,"httpStatus":400,"severity":"error","filePath":"pkg/api/norman/customization/aks/handler.go","lineNumber":337,"sourceCode":"\tif err != nil {\n\t\treturn http.StatusBadRequest, fmt.Errorf(\"cannot read request body: %v\", err)\n\t}\n\n\tif err = json.Unmarshal(raw, &cap); err != nil {\n\t\treturn http.StatusBadRequest, fmt.Errorf(\"cannot parse request body: %v\", err)\n\t}\n\n\tif cap.SubscriptionID == \"\" {\n\t\treturn http.StatusBadRequest, fmt.Errorf(\"invalid subscriptionId\")\n\t}\n\tif cap.TenantID == \"\" {\n\t\treturn http.StatusBadRequest, fmt.Errorf(\"invalid tenantId\")\n\t}\n\tif cap.ClientID == \"\" {\n\t\treturn http.StatusBadRequest, fmt.Errorf(\"invalid clientId\")\n\t}\n\tif cap.ClientSecret == \"\" {\n\t\treturn http.StatusBadRequest, fmt.Errorf(\"invalid clientSecret\")\n\t}\n\n\tclientEnvironment := \"\"\n\tif cap.Environment != \"\" {\n\t\tclientEnvironment = cap.Environment\n\t}\n\t_, azureEnvironment := GetEnvironment(clientEnvironment)\n\n\tif cap.BaseURL == \"\" {\n\t\tcap.BaseURL = azureEnvironment.ResourceManagerEndpoint\n\t}\n\tif cap.AuthBaseURL == \"\" {\n\t\tcap.AuthBaseURL = azureEnvironment.ActiveDirectoryEndpoint\n\t}\n\n\treturn http.StatusOK, nil\n}\n","sourceCodeStart":319,"sourceCodeEnd":355,"githubUrl":"https://github.com/rancher/rancher/blob/932558d4e68565aff2d2f36e89ec4a391b06e7c5/pkg/api/norman/customization/aks/handler.go#L319-L355","documentation":"Final required-field check in getCredentialsFromBody (handler.go:336): subscriptionId, tenantId and clientId are present but clientSecret is empty, returning 400 'invalid clientSecret'. This mirrors error 100 but for the inline-body flow used by AKS lister endpoints rather than the credential-check endpoint.","triggerScenarios":"Inline payload includes the three GUIDs but omits the secret, or the secret field name is misspelled/cased differently so it unmarshals to \"\".","commonSituations":"Secret left blank because the UI treats it as 'unchanged' on edit while the API expects it always; automation where the secret variable is empty in CI; secrets stored in a vault never fetched into the payload.","solutions":["Add clientSecret to the inline body with the current secret value from App registrations > Certificates & secrets","On edit flows, re-send the secret (or fetch it from your secret store) - the API has no 'keep existing' for inline bodies","Verify the key is exactly clientSecret and the value has no leading/trailing whitespace stripped by shell interpolation"],"exampleFix":"// before\nconst body = { subscriptionId, tenantId, clientId }; // edit flow omitted secret\n// after\nconst body = { subscriptionId, tenantId, clientId, clientSecret: await vault.read('azure/creds') };","handlingStrategy":"validation","validationCode":"if (!body.clientSecret || !String(body.clientSecret).trim()) throw new Error('clientSecret is required on every inline request');","typeGuard":"function hasClientSecret(b) { return typeof b?.clientSecret === 'string' && b.clientSecret.trim() !== ''; }","tryCatchPattern":"if (!hasClientSecret(body)) { body.clientSecret = await vault.read('azure/clientSecret'); }\nconst resp = await post(listEndpoint, body);","preventionTips":["Inline payloads must be complete on every call - there is no 'unchanged secret' semantics","Fetch secrets from a vault at call time instead of caching possibly-stale values","Trim/validate secrets in forms so whitespace-only values are rejected"],"tags":["aks","azure","validation","client-secret","http-400"],"backgroundTag":null,"analyzedSha":"932558d4e68565aff2d2f36e89ec4a391b06e7c5","analyzedAt":"2026-08-16T04:37:02.125Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}