{"record":{"id":"4a865b6397770d03","repo":"hashicorp/nomad","slug":"fuzzy-search-query-must-be-at-least-d-characters","errorCode":null,"errorMessage":"fuzzy search query must be at least %d characters, got %d","messagePattern":"fuzzy search query must be at least (.+?) characters, got (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nomad/search_endpoint.go","lineNumber":758,"sourceCode":"\t\treturn err\n\t}\n\n\tnamespace := args.RequestNamespace()\n\tcontext := args.Context\n\n\tif !sufficientFuzzySearchPerms(aclObj, namespace, context) {\n\t\treturn structs.ErrPermissionDenied\n\t}\n\n\t// check that fuzzy search API is enabled\n\tif !s.srv.config.SearchConfig.FuzzyEnabled {\n\t\treturn fmt.Errorf(\"fuzzy search is not enabled\")\n\t}\n\n\t// check the query term meets minimum length\n\tmin := s.srv.config.SearchConfig.MinTermLength\n\tif n := len(args.Text); n < min {\n\t\treturn fmt.Errorf(\"fuzzy search query must be at least %d characters, got %d\", min, n)\n\t}\n\n\t// for case-insensitive searching, lower-case the search term once and reuse\n\ttext := strings.ToLower(args.Text)\n\n\t// accumulate fuzzy search results and any truncations\n\treply.Matches = make(map[structs.Context][]structs.FuzzyMatch)\n\treply.Truncations = make(map[structs.Context]bool)\n\n\t// Setup the blocking query\n\topts := blockingOptions{\n\t\tqueryMeta: &reply.QueryMeta,\n\t\tqueryOpts: new(structs.QueryOptions),\n\t\trun: func(ws memdb.WatchSet, state *state.StateStore) error {\n\n\t\t\tfuzzyIters := make(map[structs.Context]memdb.ResultIterator)\n\t\t\tprefixIters := make(map[structs.Context]memdb.ResultIterator)\n","sourceCodeStart":740,"sourceCodeEnd":776,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/nomad/search_endpoint.go#L740-L776","documentation":"When fuzzy search is enabled, Nomad enforces a minimum length on the query term, configurable via SearchConfig.MinTermLength. The FuzzySearch RPC returns this error when len(args.Text) is shorter than that minimum. This prevents extremely short, high-fan-out fuzzy queries that are expensive to evaluate across all contexts.","triggerScenarios":"Sending a FuzzySearch request whose Text field is shorter than s.srv.config.SearchConfig.MinTermLength (default minimum) — e.g. searching for \"a\" or an empty string.","commonSituations":"Users typing 1-2 characters into a UI search box wired to fuzzy search; programmatic callers passing empty Text; clusters where operators raised MinTermLength above what existing clients send.","solutions":["Send a query term at least MinTermLength characters long (default is 2 or the operator-configured value)","Lower `search { min_term_length = N }` in server config if short terms are legitimately needed","Check len(text) client-side and skip/warn before issuing the RPC"],"exampleFix":"// before\nreq := &api.SearchRequest{Text: \"jo\", Context: \"jobs\"}\n// after\nif len(\"jo\") < minTermLength { /* pad or reject client-side */ }\nreq := &api.SearchRequest{Text: \"job-prefix\", Context: \"jobs\"}","handlingStrategy":"validation","validationCode":"const minTermLength = 2 // match server SearchConfig.MinTermLength\nif len(req.Text) < minTermLength {\n    return fmt.Errorf(\"query must be at least %d characters\", minTermLength)\n}","typeGuard":null,"tryCatchPattern":"resp, err := client.Search().FuzzySearch(ctx, req)\nif err != nil {\n    if strings.Contains(err.Error(), \"must be at least\") {\n        return errFuzzyTermTooShort{Term: req.Text}\n    }\n    return err\n}","preventionTips":["Validate term length client-side against the server's MinTermLength before each call","Disable/gray-out search input in UIs until the minimum length is typed","Keep client min-length in sync when operators change server config"],"tags":["nomad","go","validation","input-length"],"backgroundTag":"input-validation-failed","analyzedSha":"482b49bf1aec006f089bcfc7e632d8f6ac303e5e","analyzedAt":"2026-09-04T07:54:14.808Z","contentChangedAt":"2026-09-04T07:54:14.808Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}