{"record":{"id":"ded9a88e7db38db1","repo":"jaegertracing/jaeger","slug":"span-ids-is-required-and-must-not-be-empty","errorCode":null,"errorMessage":"span_ids is required and must not be empty","messagePattern":"span_ids is required and must not be empty","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/jaeger/internal/extension/jaegerquery/internal/mcptools/internal/handlers/get_span_details.go","lineNumber":131,"sourceCode":"\t\tfor spanID := range spanIDSet {\n\t\t\tmissingIDs = append(missingIDs, spanID)\n\t\t}\n\t\toutput.Error = fmt.Sprintf(\"spans not found: %v\", missingIDs)\n\t}\n\n\treturn nil, output, nil\n}\n\n// buildQuery converts GetSpanDetailsInput to querysvc.GetTraceParams and returns\n// the requested span IDs in canonical lowercase hex form for the lookup set.\nfunc (h *getSpanDetailsHandler) buildQuery(input types.GetSpanDetailsInput) (querysvc.GetTraceParams, []string, error) {\n\t// Validate input\n\tif input.TraceID == \"\" {\n\t\treturn querysvc.GetTraceParams{}, nil, errors.New(\"trace_id is required\")\n\t}\n\n\tif len(input.SpanIDs) == 0 {\n\t\treturn querysvc.GetTraceParams{}, nil, errors.New(\"span_ids is required and must not be empty\")\n\t}\n\n\t// Validate span count against configured limit\n\tif len(input.SpanIDs) > h.maxSpanDetailsPerRequest {\n\t\treturn querysvc.GetTraceParams{}, nil, fmt.Errorf(\n\t\t\t\"span_ids exceeds maximum limit: requested %d, max allowed %d\",\n\t\t\tlen(input.SpanIDs),\n\t\t\th.maxSpanDetailsPerRequest,\n\t\t)\n\t}\n\n\ttraceID, err := parseTraceID(input.TraceID)\n\tif err != nil {\n\t\treturn querysvc.GetTraceParams{}, nil, fmt.Errorf(\"invalid trace_id: %w\", err)\n\t}\n\n\t// Validate every span_id up front so a malformed value fails fast instead of\n\t// triggering a backend query that can never match a real span ID. Collect the","sourceCodeStart":113,"sourceCodeEnd":149,"githubUrl":"https://github.com/jaegertracing/jaeger/blob/806f4447841ecdb60519f408b004a599d515f437/cmd/jaeger/internal/extension/jaegerquery/internal/mcptools/internal/handlers/get_span_details.go#L113-L149","documentation":"The get_span_details handler limits how many spans may be requested per call (h.maxSpanDetailsPerRequest) to keep responses bounded. This error is thrown in buildQuery when len(input.SpanIDs) exceeds that configured limit, before any query is issued.","triggerScenarios":"Passing more span IDs in the span_ids array than the configured maxSpanDetailsPerRequest cap, e.g. requesting hundreds of spans from a wide trace in one call.","commonSituations":"Trace with thousands of spans (fan-out/batch jobs) and a client requesting all spans at once; a low configured limit after deployment hardening; duplicated IDs inflating the count.","solutions":["Batch the request: split span_ids into chunks at or below the limit and call repeatedly","Deduplicate span_ids before calling (the handler builds a set anyway)","Raise maxSpanDetailsPerRequest configuration if responses are legitimately large","Narrow the span selection to only the spans you actually need"],"exampleFix":"// before\nout, err := h.Handle(ctx, req, types.GetSpanDetailsInput{TraceID: tid, SpanIDs: allSpanIDs})\n// after\nfor i := 0; i < len(allSpanIDs); i += maxLimit {\n    end := min(i+maxLimit, len(allSpanIDs))\n    out, err := h.Handle(ctx, req, types.GetSpanDetailsInput{TraceID: tid, SpanIDs: allSpanIDs[i:end]})\n    // collect results...\n}","handlingStrategy":"validation","validationCode":"uniq := make(map[string]struct{}, len(input.SpanIDs))\nfor _, id := range input.SpanIDs { uniq[id] = struct{}{} }\nif len(uniq) > maxSpanDetailsPerRequest {\n    return fmt.Errorf(\"%d unique span IDs exceeds limit %d; batch the request\", len(uniq), maxSpanDetailsPerRequest)\n}","typeGuard":null,"tryCatchPattern":"out, err := handler.Handle(ctx, req, input)\nif err != nil && strings.Contains(err.Error(), \"exceeds maximum limit\") {\n    // split input.SpanIDs into chunks <= limit and issue multiple calls\n}","preventionTips":["Chunk large span ID lists before calling","Deduplicate IDs first","Check the deployment's maxSpanDetailsPerRequest config when planning request sizes"],"tags":["jaeger","mcp","validation","limit-exceeded"],"backgroundTag":"request-limit-exceeded","analyzedSha":"806f4447841ecdb60519f408b004a599d515f437","analyzedAt":"2026-09-01T02:39:22.140Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}