{"record":{"id":"429c6d53786b1e4f","repo":"googleapis/mcp-toolbox","slug":"model-s-returned-d-embeddings-for-d-inputs","errorCode":null,"errorMessage":"model %s returned %d embeddings for %d inputs","messagePattern":"model (.+?) returned (.+?) embeddings for (.+?) inputs","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/util/parameters/parameters.go","lineNumber":224,"sourceCode":"\tfor modelName, params := range parametersToEmbed {\n\t\tmodel, ok := pMgr.GetEmbeddingModel(modelName)\n\t\tif !ok {\n\t\t\treturn nil, fmt.Errorf(\"embedding model does not exist: %s\", modelName)\n\t\t}\n\n\t\t// Extract only the string values for the API call\n\t\tstringBatch := make([]string, len(params))\n\t\tfor i, paramStr := range params {\n\t\t\tstringBatch[i] = paramStr.OriginalValue\n\t\t}\n\n\t\tembeddings, err := model.EmbedParameters(ctx, stringBatch)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"error embedding parameters with model %s: %w\", modelName, err)\n\t\t}\n\n\t\tif len(embeddings) != len(stringBatch) {\n\t\t\treturn nil, fmt.Errorf(\"model %s returned %d embeddings for %d inputs\", modelName, len(embeddings), len(stringBatch))\n\t\t}\n\n\t\tfor i, rawVector := range embeddings {\n\n\t\t\titem := params[i]\n\n\t\t\t// Call vector formatter\n\t\t\tvar finalValue any = rawVector\n\n\t\t\tif formatter == nil {\n\t\t\t\tparamValues[item.Index].Value = finalValue\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tformattedVector := formatter(rawVector)\n\t\t\tfinalValue = formattedVector\n\t\t\tparamValues[item.Index].Value = finalValue\n\t\t}","sourceCodeStart":206,"sourceCodeEnd":242,"githubUrl":"https://github.com/googleapis/mcp-toolbox/blob/8cc6e09de2ad7b8bffc77751799585a1401a48eb/internal/util/parameters/parameters.go#L206-L242","documentation":"This sanity check fires when the embedding model returns a different number of vectors than the number of input strings sent. The library requires a strict 1:1 mapping to attach each vector back to its parameter. It almost always indicates a bug or contract violation in the embedding model implementation, not in caller code.","triggerScenarios":"model.EmbedParameters returns a slice whose length differs from len(stringBatch): a custom model implementation silently dropping failed inputs, truncating batches, paginating without concatenating pages, or the provider omitting embeddings for content-filtered inputs.","commonSituations":"Custom or third-party embedding model wrappers that skip failed items instead of erroring; provider content filtering on some inputs; batch pagination bugs; implementations that deduplicate identical input strings.","solutions":["Fix the model's EmbedParameters implementation so it returns exactly one embedding per input or a non-nil error.","Log the raw provider response to identify which inputs were dropped (e.g. content filtering, empty strings).","In a paginating wrapper, concatenate every page's results before returning.","Handle empty or filtered inputs explicitly with a placeholder vector or an error so the result count is preserved."],"exampleFix":"// before: drops failed inputs, breaking 1:1 mapping\nout := []vector{}\nfor _, b := range batch {\n    v, err := embedOne(b)\n    if err != nil { continue }\n    out = append(out, v)\n}\n\n// after: error instead of shrinking the result\nout := make([]vector, 0, len(batch))\nfor _, b := range batch {\n    v, err := embedOne(b)\n    if err != nil { return nil, err }\n    out = append(out, v)\n}","handlingStrategy":"type-guard","validationCode":"if got := len(embeddings); got != len(batch) {\n    return fmt.Errorf(\"model returned %d embeddings for %d inputs\", got, len(batch))\n}","typeGuard":"func embeddingsMatchInputs(embeds []Embedding, inputs []string) bool {\n    return len(embeds) == len(inputs)\n}","tryCatchPattern":"if err != nil {\n    if strings.Contains(err.Error(), \"returned\") && strings.Contains(err.Error(), \"embeddings\") {\n        // log inputs, flag model implementation bug, skip cache write\n    }\n    return err\n}","preventionTips":["For custom embedding models, assert 1:1 input/output counts in the model's own unit tests.","Never silently drop failed inputs; return an error instead.","Log the raw provider response when counts diverge to find dropped items.","Concatenate all pages in paginating wrappers before returning."],"tags":["embeddings","contract-violation","go"],"backgroundTag":"embedding-count-mismatch","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"}