googleapis/mcp-toolbox · error
error fetching LookML model %s: %w
Error message
error fetching LookML model %s: %w
What it means
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).
Source
Thrown at internal/tools/looker/lookerhealthvacuum/lookerhealthvacuum.go:376
return nil, err
}
var data []map[string]interface{}
_ = json.Unmarshal([]byte(raw), &data)
results := make(map[string]int)
for _, row := range data {
model, _ := row["query.model"].(string)
count, _ := row["history.query_run_count"].(float64)
results[model] = int(count)
}
return results, nil
}
func (t *vacuumTool) getUnusedExplores(ctx context.Context, modelName string) ([]string, error) {
lookmlModel, err := t.SdkClient.LookmlModel(modelName, "", nil)
if err != nil {
return nil, fmt.Errorf("error fetching LookML model %s: %w", modelName, err)
}
var unusedExplores []string
if lookmlModel.Explores != nil {
for _, e := range *lookmlModel.Explores {
limit := "1"
queryCountQueryBody := &v4.WriteQuery{
Model: "system__activity",
View: "history",
Fields: &[]string{"history.query_run_count"},
Filters: &map[string]any{
"query.model": modelName,
"query.view": *e.Name,
"history.created_date": fmt.Sprintf("%d days", t.timeframe),
"history.query_run_count": fmt.Sprintf(">%d", t.minQueries-1),
"user.dev_branch_name": "NULL",
},
Limit: &limit,View on GitHub (pinned to 8cc6e09de2)
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.
Example fix
// before
lookmlModel, err := t.SdkClient.LookmlModel(modelName, "", nil)
if err != nil {
return nil, fmt.Errorf("error fetching LookML model %s: %w", modelName, err)
}
// after — tolerate a model vanishing mid-run
lookmlModel, err := t.SdkClient.LookmlModel(modelName, "", nil)
if err != nil {
logger.WarnContext(ctx, "skipping model", "model", modelName, "err", err)
return nil, nil
} Defensive patterns
Strategy: try-catch
Validate before calling
// confirm the model exists before deep-fetching
models, err := sdk.AllLookmlModels(v4.RequestAllLookmlModels{}, nil)
if err != nil { return err }
found := false
for _, m := range models {
if m.Name != nil && *m.Name == modelName { found = true }
}
if !found { return fmt.Errorf("model %q not found", modelName) } Try / catch
lookmlModel, err := sdk.LookmlModel(modelName, "", nil)
if err != nil {
logger.WarnContext(ctx, "skipping model", "model", modelName, "err", err)
return nil, nil // tolerate per-model failures during bulk vacuum
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- error fetching LookML models: %w
- failed to verify allowedDataset '%s' in project '%s': %w
- incorrect settings: %w
- API returned non-200 status: %d %s
- error fetching connections: %w
AI-assisted analysis of googleapis/mcp-toolbox@8cc6e09de2 (2026-09-05).
Data as JSON: /api/errors/695fc88a1c46133a.
Report an issue: GitHub.