{"record":{"id":"14b75a1408107429","repo":"googleapis/mcp-toolbox","slug":"resources-cannot-be-empty","errorCode":null,"errorMessage":"resources cannot be empty","messagePattern":"resources cannot be empty","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/tools/dataplex/dataplexlookupcontext/dataplexlookupcontext.go","lineNumber":122,"sourceCode":"\t\treturn fmt.Errorf(\"invalid source for %q tool: source %q is not a compatible type\", t.Cfg.Type, t.Cfg.Source)\n\t}\n\treturn nil\n}\n\nfunc (t Tool) Invoke(ctx context.Context, s sources.Source, params parameters.ParamValues, accessToken tools.AccessToken) (any, util.ToolboxError) {\n\tsource, ok := s.(compatibleSource)\n\tif !ok {\n\t\treturn nil, util.NewClientServerError(\"source used is not compatible with the tool\", http.StatusInternalServerError, nil)\n\t}\n\tparamsMap := params.AsMap()\n\tresourcesSlice, err := parameters.ConvertAnySliceToTyped(paramsMap[\"resources\"].([]any), \"string\")\n\tif err != nil {\n\t\treturn nil, util.NewAgentError(fmt.Sprintf(\"can't convert resources to array of strings: %s\", err), err)\n\t}\n\tresources := resourcesSlice.([]string)\n\n\tif len(resources) == 0 {\n\t\terr := fmt.Errorf(\"resources cannot be empty\")\n\t\treturn nil, util.NewAgentError(err.Error(), err)\n\t}\n\tvar name string\n\tvar firstLocation string\n\tfor i, resource := range resources {\n\t\tparts := strings.Split(resource, \"/\")\n\t\tif len(parts) < 4 || parts[0] != \"projects\" || parts[2] != \"locations\" {\n\t\t\terr := fmt.Errorf(\"invalid resource format at index %d, must be in the format of projects/{project_id_or_number}/locations/{location}/entryGroups/{group}/entries/{entry}\", i)\n\t\t\treturn nil, util.NewAgentError(err.Error(), err)\n\t\t}\n\n\t\tlocation := parts[3]\n\t\tif i == 0 {\n\t\t\tfirstLocation = location\n\t\t\tproject := source.ProjectID()\n\t\t\tname = fmt.Sprintf(\"projects/%s/locations/%s\", project, location)\n\t\t} else if location != firstLocation {\n\t\t\terr := fmt.Errorf(\"all resources must belong to the same location. Please make separate calls for each distinct location\")","sourceCodeStart":104,"sourceCodeEnd":140,"githubUrl":"https://github.com/googleapis/mcp-toolbox/blob/8cc6e09de2ad7b8bffc77751799585a1401a48eb/internal/tools/dataplex/dataplexlookupcontext/dataplexlookupcontext.go#L104-L140","documentation":"dataplex-lookup-context accepts a `resources` array parameter naming Dataplex entries to resolve. Invoke rejects the call when the converted array is empty, because the underlying Dataplex LookupContext API needs at least one resource. It surfaces as an AgentError to the LLM/client.","triggerScenarios":"Invoking dataplex-lookup-context with resources: [] (empty array) or a parameter that converts to a zero-length string slice.","commonSituations":"LLM agent omits or sends an empty resources list; client template renders no values into the array; upstream filtering removed all items before the call.","solutions":["Pass at least one fully-qualified entry resource in the resources array","Validate the array is non-empty before invoking the tool","If the intent is a broad search, use dataplex-search-entries instead"],"exampleFix":"// before\n{\"resources\": []}\n// after\n{\"resources\": [\"projects/my-proj/locations/us-central1/entryGroups/my-group/entries/my-entry\"]}","handlingStrategy":"validation","validationCode":"if len(resources) == 0 {\n\treturn fmt.Errorf(\"resources must contain at least one fully-qualified entry name\")\n}","typeGuard":null,"tryCatchPattern":"resp, terr := tool.Invoke(ctx, src, params, token)\nif terr != nil {\n\t// AgentError: empty resources — repopulate the list before retrying\n\treturn handleAgentError(terr)\n}","preventionTips":["Check array length before invoking lookup-context","Have agents fall back to dataplex-search-entries when no specific resources are known","Validate tool parameters with JSON schema constraints (minItems) client-side"],"tags":["go","dataplex","validation","empty-input"],"backgroundTag":"empty-required-parameter","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"}