{"record":{"id":"695fc88a1c46133a","repo":"googleapis/mcp-toolbox","slug":"error-fetching-lookml-model-s-w","errorCode":null,"errorMessage":"error fetching LookML model %s: %w","messagePattern":"error fetching LookML model (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/tools/looker/lookerhealthvacuum/lookerhealthvacuum.go","lineNumber":376,"sourceCode":"\t\treturn nil, err\n\t}\n\n\tvar data []map[string]interface{}\n\t_ = json.Unmarshal([]byte(raw), &data)\n\n\tresults := make(map[string]int)\n\tfor _, row := range data {\n\t\tmodel, _ := row[\"query.model\"].(string)\n\t\tcount, _ := row[\"history.query_run_count\"].(float64)\n\t\tresults[model] = int(count)\n\t}\n\treturn results, nil\n}\n\nfunc (t *vacuumTool) getUnusedExplores(ctx context.Context, modelName string) ([]string, error) {\n\tlookmlModel, err := t.SdkClient.LookmlModel(modelName, \"\", nil)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"error fetching LookML model %s: %w\", modelName, err)\n\t}\n\n\tvar unusedExplores []string\n\tif lookmlModel.Explores != nil {\n\t\tfor _, e := range *lookmlModel.Explores {\n\t\t\tlimit := \"1\"\n\t\t\tqueryCountQueryBody := &v4.WriteQuery{\n\t\t\t\tModel:  \"system__activity\",\n\t\t\t\tView:   \"history\",\n\t\t\t\tFields: &[]string{\"history.query_run_count\"},\n\t\t\t\tFilters: &map[string]any{\n\t\t\t\t\t\"query.model\":             modelName,\n\t\t\t\t\t\"query.view\":              *e.Name,\n\t\t\t\t\t\"history.created_date\":    fmt.Sprintf(\"%d days\", t.timeframe),\n\t\t\t\t\t\"history.query_run_count\": fmt.Sprintf(\">%d\", t.minQueries-1),\n\t\t\t\t\t\"user.dev_branch_name\":    \"NULL\",\n\t\t\t\t},\n\t\t\t\tLimit: &limit,","sourceCodeStart":358,"sourceCodeEnd":394,"githubUrl":"https://github.com/googleapis/mcp-toolbox/blob/8cc6e09de2ad7b8bffc77751799585a1401a48eb/internal/tools/looker/lookerhealthvacuum/lookerhealthvacuum.go#L358-L394","documentation":"getUnusedExplores fetches a single LookML model by name via the Looker SDK's LookmlModel(modelName, \"\", nil) to inspect its explores. When that per-model API call fails, the error is wrapped as \"error fetching LookML model <name>: %w\". Unlike the list-all failures, this one names the specific model, pointing to a model-level problem (deleted/renamed model, per-model permission, or transient API error).","triggerScenarios":"t.SdkClient.LookmlModel(modelName, \"\", nil) returns an error while iterating models discovered earlier: the model was deleted or renamed between calls, the API user cannot read that model, a 404 from Looker, rate limiting, or network interruption mid-run.","commonSituations":"Concurrent LookML deploys removing models during a long vacuum run; dev-mode model not visible to the API user's workspace; permission-scoped roles; 429 rate limit triggered by iterating many models rapidly.","solutions":["Confirm the model named in the error still exists and check its exact name casing in Looker.","Verify the API user has permission to read that specific model/workspace.","Add retry/backoff around per-model calls to survive 429s and transient failures.","Re-run the vacuum to pick up models changed by a concurrent LookML deploy."],"exampleFix":"// before\nlookmlModel, err := t.SdkClient.LookmlModel(modelName, \"\", nil)\nif err != nil {\n    return nil, fmt.Errorf(\"error fetching LookML model %s: %w\", modelName, err)\n}\n\n// after — tolerate a model vanishing mid-run\nlookmlModel, err := t.SdkClient.LookmlModel(modelName, \"\", nil)\nif err != nil {\n    logger.WarnContext(ctx, \"skipping model\", \"model\", modelName, \"err\", err)\n    return nil, nil\n}","handlingStrategy":"try-catch","validationCode":"// confirm the model exists before deep-fetching\nmodels, err := sdk.AllLookmlModels(v4.RequestAllLookmlModels{}, nil)\nif err != nil { return err }\nfound := false\nfor _, m := range models {\n    if m.Name != nil && *m.Name == modelName { found = true }\n}\nif !found { return fmt.Errorf(\"model %q not found\", modelName) }","typeGuard":null,"tryCatchPattern":"lookmlModel, err := sdk.LookmlModel(modelName, \"\", nil)\nif err != nil {\n    logger.WarnContext(ctx, \"skipping model\", \"model\", modelName, \"err\", err)\n    return nil, nil // tolerate per-model failures during bulk vacuum\n}","preventionTips":["Treat per-model fetch failures as non-fatal in bulk vacuum loops.","Avoid running vacuums concurrently with LookML deploys.","Add throttling/backoff to prevent 429s when iterating many models.","Verify API user workspace/permissions cover all target models."],"tags":["looker","api","sdk","permissions"],"backgroundTag":"looker-api-request-failed","analyzedSha":"8cc6e09de2ad7b8bffc77751799585a1401a48eb","analyzedAt":"2026-09-05T01:10:36.887Z","contentChangedAt":"2026-09-05T01:10:36.887Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}