{"record":{"id":"3e90d1d6a905325f","repo":"wtfutil/wtf","slug":"failed-to-create-azure-logs-client-for-subscriptio","errorCode":null,"errorMessage":"failed to create Azure Logs client for subscription %s: %w","messagePattern":"failed to create Azure Logs client for subscription (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"modules/azurelogs/query.go","lineNumber":61,"sourceCode":"\t// Use read lock first to check if client exists\n\tclientsMutex.RLock()\n\tclient := LogQueryClients[qf.SubscriptionID]\n\tclientsMapExists := LogQueryClients != nil\n\tclientsMutex.RUnlock()\n\n\t// If map doesn't exist or client doesn't exist, we need write access\n\tif !clientsMapExists || client == nil {\n\t\tclientsMutex.Lock()\n\t\t// Double-check after acquiring write lock (double-checked locking pattern)\n\t\tif LogQueryClients == nil {\n\t\t\tLogQueryClients = make(map[string]*azquery.LogsClient)\n\t\t}\n\n\t\tif LogQueryClients[qf.SubscriptionID] == nil {\n\t\t\tLogQueryClients[qf.SubscriptionID], err = CreateLogsClient(sess, qf.SubscriptionID)\n\t\t\tif err != nil {\n\t\t\t\tclientsMutex.Unlock()\n\t\t\t\treturn nil, fmt.Errorf(\"failed to create Azure Logs client for subscription %s: %w\", qf.SubscriptionID, err)\n\t\t\t}\n\t\t}\n\t\tclient = LogQueryClients[qf.SubscriptionID]\n\t\tclientsMutex.Unlock()\n\t}\n\n\tres, err := client.QueryWorkspace(\n\t\tcontext.Background(),\n\t\tqf.WorkspaceID,\n\t\tazquery.Body{\n\t\t\tQuery: to.Ptr(qf.Query),\n\t\t},\n\t\tnil)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to execute query on workspace %s: %w\", qf.WorkspaceID, err)\n\t}\n\n\tif res.Error != nil {","sourceCodeStart":43,"sourceCodeEnd":79,"githubUrl":"https://github.com/wtfutil/wtf/blob/bb838c1ccb0f0f3223690df44afdec663d622881/modules/azurelogs/query.go#L43-L79","documentation":"RunQuery lazily creates an Azure Log Analytics client per subscription via CreateLogsClient and caches it in LogQueryClients. When client creation fails, this error wraps the underlying cause (almost always authentication/credential failure). It is returned while holding the clients mutex, which is unlocked before returning.","triggerScenarios":"RunQuery or fetchDataAsync on a subscription with no cached client where CreateLogsClient returns an error: missing/unreadable Azure credentials (az CLI not logged in, missing AZURE_* env vars), wrong tenant, or invalid subscription ID.","commonSituations":"DefaultAzureCredential finding no credential source (no az login, no managed identity, no AZURE_CLIENT_SECRET), expired az CLI login, or a typo'd subscription GUID.","solutions":["Re-authenticate: run `az login` or set AZURE_TENANT_ID / AZURE_CLIENT_ID / AZURE_CLIENT_SECRET env vars","Check the wrapped error (%w) for the exact credential failure and fix that source","Verify the subscription ID GUID is correct and the account has Reader (or Log Analytics Reader) access","If hosting in Azure, ensure the managed identity has the Log Analytics Reader role on the workspace"],"exampleFix":"// before: running locally with no credentials\n// shell: ./azurelogs-runner\n// after\n// shell: az login && ./azurelogs-runner\n// or export AZURE_TENANT_ID=... AZURE_CLIENT_ID=... AZURE_CLIENT_SECRET=...","handlingStrategy":"try-catch","validationCode":"// pre-check credential availability\ncred, err := azidentity.NewDefaultAzureCredential(nil)\nif err != nil {\n    return fmt.Errorf(\"no Azure credential available: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"tables, err := RunQuery(sess)\nif err != nil {\n    var ae *azidentity.AuthenticationFailedError\n    if errors.As(err, &ae) {\n        return fmt.Errorf(\"re-authenticate (az login / service principal): %w\", err)\n    }\n    return err\n}","preventionTips":["Run `az login` (or provision a service principal) before starting the app","Ensure the identity has Log Analytics Reader on the workspace","Monitor service-principal secret expiry and rotate proactively"],"tags":["azure","authentication","client-creation","log-analytics"],"backgroundTag":"azure-credential-error","analyzedSha":"bb838c1ccb0f0f3223690df44afdec663d622881","analyzedAt":"2026-09-03T17:02:45.030Z","contentChangedAt":"2026-09-03T17:02:45.030Z","schemaVersion":2},"datasetVersion":"2026-09-11T00:17:11.886Z"}