{"record":{"id":"269e04a097727335","repo":"wtfutil/wtf","slug":"azure-workspace-id-is-required-but-not-configured","errorCode":null,"errorMessage":"azure workspace ID is required but not configured","messagePattern":"azure workspace ID is required but not configured","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"modules/azurelogs/query.go","lineNumber":36,"sourceCode":"\n// TableRow represents a single row of data from Azure Log Analytics\ntype TableRow []string\n\n// TableResp represents the response from an Azure Log Analytics query\ntype TableResp struct {\n\tHeader []string   // Column headers\n\tRows   []TableRow // Data rows\n}\n\n// RunQuery executes an Azure Log Analytics query and returns the formatted results\nfunc RunQuery(sess *Session) (*TableResp, error) {\n\tqf := sess.QueryFile\n\tvar err error\n\tvar tableResp TableResp\n\ttableResp.Header = qf.Columns\n\n\tif qf.WorkspaceID == \"\" {\n\t\treturn nil, fmt.Errorf(\"azure workspace ID is required but not configured\")\n\t}\n\n\tif qf.SubscriptionID == \"\" {\n\t\treturn nil, fmt.Errorf(\"azure subscription ID is required but not configured\")\n\t}\n\n\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)","sourceCodeStart":18,"sourceCodeEnd":54,"githubUrl":"https://github.com/wtfutil/wtf/blob/bb838c1ccb0f0f3223690df44afdec663d622881/modules/azurelogs/query.go#L18-L54","documentation":"RunQuery in modules/azurelogs/query.go:36 refuses to run when the parsed QueryFile has an empty WorkspaceID. The workspace ID identifies the Azure Log Analytics workspace to query, so without it the API call would be invalid. The library throws this as an explicit pre-flight validation before any Azure API call.","triggerScenarios":"Calling RunQuery (directly or via fetchDataAsync) when the session's QueryFile.WorkspaceID is the empty string — i.e. the query config YAML omitted the workspace ID key or set it to an empty value.","commonSituations":"Query config file missing the workspace-id field, empty value after an environment-variable substitution that did not resolve, or a struct with wrong yaml tags so the field never gets populated during unmarshal.","solutions":["Add the workspace ID to the query config YAML (e.g. workspace-id: <guid>) and re-run Init","Verify the yaml tag on the WorkspaceID struct field matches the key used in the config file","Check that any env-var placeholder in the config (e.g. ${WORKSPACE_ID}) is actually set in the environment","Print/log sess.QueryFile after Init to confirm the field was parsed"],"exampleFix":"// before (query.yml)\nsubscription-id: abc-123\nquery: \"AzureActivity | take 10\"\n// after (query.yml)\nworkspace-id: 00000000-0000-0000-0000-000000000000\nsubscription-id: abc-123\nquery: \"AzureActivity | take 10\"","handlingStrategy":"validation","validationCode":"if sess.QueryFile.WorkspaceID == \"\" {\n    return errors.New(\"workspace-id missing in query config; set it before RunQuery\")\n}","typeGuard":null,"tryCatchPattern":"tables, err := RunQuery(sess)\nif err != nil {\n    if strings.Contains(err.Error(), \"workspace ID is required\") {\n        return fmt.Errorf(\"config: add workspace-id to %s\", queryPath)\n    }\n    return err\n}","preventionTips":["Include workspace-id in every query file template","Validate required fields right after Init and fail fast with a clear message","Load IDs from environment variables with defaults checked at startup"],"tags":["azure","configuration","log-analytics","validation"],"backgroundTag":"missing-config-field","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"}