{"id":"46af6a484fd40e81","repo":"labstack/echo","slug":"extractor-source-for-lookup-could-not-be-split-int","errorCode":null,"errorMessage":"extractor source for lookup could not be split into needed parts: %v","messagePattern":"extractor source for lookup could not be split into needed parts: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"middleware/extractor.go","lineNumber":93,"sourceCode":"\treturn createExtractors(lookups, limit)\n}\n\nfunc createExtractors(lookups string, limit uint) ([]ValuesExtractor, error) {\n\tif lookups == \"\" {\n\t\treturn nil, nil\n\t}\n\tif limit == 0 {\n\t\tlimit = 1\n\t} else if limit > extractorLimit {\n\t\tlimit = extractorLimit\n\t}\n\n\tsources := strings.SplitSeq(lookups, \",\")\n\tvar extractors = make([]ValuesExtractor, 0)\n\tfor source := range sources {\n\t\tparts := strings.Split(source, \":\")\n\t\tif len(parts) < 2 {\n\t\t\treturn nil, fmt.Errorf(\"extractor source for lookup could not be split into needed parts: %v\", source)\n\t\t}\n\n\t\tswitch parts[0] {\n\t\tcase \"query\":\n\t\t\textractors = append(extractors, valuesFromQuery(parts[1], limit))\n\t\tcase \"param\":\n\t\t\textractors = append(extractors, valuesFromParam(parts[1], limit))\n\t\tcase \"cookie\":\n\t\t\textractors = append(extractors, valuesFromCookie(parts[1], limit))\n\t\tcase \"form\":\n\t\t\textractors = append(extractors, valuesFromForm(parts[1], limit))\n\t\tcase \"header\":\n\t\t\tprefix := \"\"\n\t\t\tif len(parts) > 2 {\n\t\t\t\tprefix = parts[2]\n\t\t\t}\n\t\t\textractors = append(extractors, valuesFromHeader(parts[1], prefix, limit))\n\t\t}","sourceCodeStart":75,"sourceCodeEnd":111,"githubUrl":"https://github.com/labstack/echo/blob/05489dc1730161df26b72d1ae2a3ba6fb8178fc7/middleware/extractor.go#L75-L111","documentation":"Returned by CreateExtractors / createExtractors (middleware/extractor.go:90-94) when a comma-separated lookup source has no ':' separator, so it cannot be split into <source>:<name>. Each source must have at least two parts; an unknown source name (e.g. a typo) silently produces no extractor but does NOT error — only the missing colon does.","triggerScenarios":"Passing \"Authorization\" (missing the 'header:' prefix), \"header\" (missing ':name'), or \"header:Authorization,query\" (second source lacks ':') to a middleware KeyAuth/JWT extractor `Lookup`/`TokenLookup` option.","commonSituations":"Configuring middleware KeyAuth, JWT, or RequestID with a custom lookup string and forgetting the 'source:name' format; trailing comma leaving an empty segment.","solutions":["Format every source as '<source>:<name>' (header:Authorization, query:token, param:id, cookie:session, form:field)","Drop trailing commas and empty segments","Build the lookup string from constants/validated parts rather than free text"],"exampleFix":"// before\n_ = middleware.KeyAuthWithConfig(middleware.KeyAuthConfig{\n    KeyLookup: \"Authorization\",\n})\n// after\n_ = middleware.KeyAuthWithConfig(middleware.KeyAuthConfig{\n    KeyLookup: \"header:Authorization\",\n})","handlingStrategy":"validation","validationCode":"func validLookup(s string) error {\n    for _, src := range strings.Split(s, \",\") {\n        if strings.TrimSpace(src) == \"\" { continue }\n        if len(strings.Split(src, \":\")) < 2 {\n            return fmt.Errorf(\"bad lookup source %q (want 'source:name')\", src)\n        }\n    }\n    return nil\n}\nif err := validLookup(cfg.KeyLookup); err != nil { return err }","typeGuard":null,"tryCatchPattern":"ext, err := middleware.CreateExtractors(lookup, 1)\nif err != nil {\n    return fmt.Errorf(\"invalid extractor config %q: %w\", lookup, err)\n}","preventionTips":["Format every source as 'source:name'","Build lookup strings from validated parts, not free text","Reject empty trailing segments"],"tags":["middleware","extractor","configuration"],"analyzedSha":"05489dc1730161df26b72d1ae2a3ba6fb8178fc7","analyzedAt":"2026-08-04T21:32:47.783Z","schemaVersion":2}