{"record":{"id":"d6250ed74b4c13e3","repo":"langchain-ai/langchain","slug":"tags-must-be-a-list-of-the-same-length-as-prompts","errorCode":null,"errorMessage":"tags must be a list of the same length as prompts","messagePattern":"tags must be a list of the same length as prompts","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"libs/core/langchain_core/language_models/llms.py","lineNumber":944,"sourceCode":"                **self._get_ls_params_with_defaults(stop=stop, **kwargs),\n            }\n        if (\n            isinstance(callbacks, list)\n            and callbacks\n            and (\n                isinstance(callbacks[0], (list, BaseCallbackManager))\n                or callbacks[0] is None\n            )\n        ):\n            # We've received a list of callbacks args to apply to each input\n            if len(callbacks) != len(prompts):\n                msg = \"callbacks must be the same length as prompts\"\n                raise ValueError(msg)\n            if tags is not None and not (\n                isinstance(tags, list) and len(tags) == len(prompts)\n            ):\n                msg = \"tags must be a list of the same length as prompts\"\n                raise ValueError(msg)\n            if metadata is not None and not (\n                isinstance(metadata, list) and len(metadata) == len(prompts)\n            ):\n                msg = \"metadata must be a list of the same length as prompts\"\n                raise ValueError(msg)\n            if run_name is not None and not (\n                isinstance(run_name, list) and len(run_name) == len(prompts)\n            ):\n                msg = \"run_name must be a list of the same length as prompts\"\n                raise ValueError(msg)\n            tags_list = cast(\"list[list[str] | None]\", tags or ([None] * len(prompts)))\n            metadata_list = cast(\n                \"list[builtins.dict[str, Any] | None]\",\n                metadata or ([{}] * len(prompts)),\n            )\n            run_name_list = run_name or cast(\n                \"list[str | None]\", ([None] * len(prompts))\n            )","sourceCodeStart":926,"sourceCodeEnd":962,"githubUrl":"https://github.com/langchain-ai/langchain/blob/e32fa9a52eab3b61ad7a45399bfde59b3e580fc4/libs/core/langchain_core/language_models/llms.py#L926-L962","documentation":"Raised by BaseLLM.generate when processing a batch of prompts with per-prompt callbacks. When callbacks is passed as a list of per-prompt callback configs, any tags argument must be a list of exactly the same length as the prompts list. This validation runs only in the per-prompt-callbacks branch (callbacks[0] is itself a list, a BaseCallbackManager, or None).","triggerScenarios":"Calling llm.generate(prompts, callbacks=[[cb1], [cb2]], tags=['a']) with 2 prompts but 1 tag; or passing tags as a flat list of tag strings while callbacks is a list of lists. Only triggers when callbacks is a list whose first element is a list/BaseCallbackManager/None.","commonSituations":"Migrating from single-prompt invoke to batched generate and reusing a single tags value; passing tags=['my-tag'] (flat, meaning one tag for all) while using per-prompt callbacks; mixing per-prompt and shared callback conventions in tracing pipelines.","solutions":["Make tags a list with exactly len(prompts) entries, e.g. tags=['my-tag'] * len(prompts), when using per-prompt callbacks","Or pass tags=None to omit per-prompt tags entirely","Or switch callbacks to a single shared callback manager/list if you want one tags list applied to all prompts"],"exampleFix":"# before\nllm.generate(prompts, callbacks=[[cb1], [cb2]], tags=['trace'])\n# after\nllm.generate(prompts, callbacks=[[cb1], [cb2]], tags=[['trace'], ['trace']])","handlingStrategy":"validation","validationCode":"n = len(prompts)\nassert isinstance(callbacks, list) and len(callbacks) == n, 'per-prompt callbacks must match prompts'\nassert tags is None or (isinstance(tags, list) and len(tags) == n), 'tags must match prompts'","typeGuard":"def valid_batch_tags(tags: object, n: int) -> bool:\n    return tags is None or (isinstance(tags, list) and len(tags) == n and all(isinstance(t, list) for t in tags))","tryCatchPattern":"try:\n    llm.generate(prompts, callbacks=cbs, tags=tags)\nexcept ValueError as e:\n    if 'same length as prompts' in str(e):\n        tags = [None] * len(prompts)\n        llm.generate(prompts, callbacks=cbs, tags=tags)\n    else:\n        raise","preventionTips":["Build callbacks, tags, metadata, run_name in one loop over prompts so lengths cannot diverge","Prefer llm.batch(prompts, config=[]) which handles per-run config objects with less footgun surface","Wrap batch construction in a helper that asserts all per-prompt lists share len(prompts)"],"tags":["llm","batch","callbacks","validation"],"backgroundTag":null,"analyzedSha":"e32fa9a52eab3b61ad7a45399bfde59b3e580fc4","analyzedAt":"2026-08-14T18:42:09.092Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}