Skip to content

model_tokens leaks to OpenAI client on plain llm config path (TypeError: unexpected keyword argument 'model_tokens') #1099

Closed

Description

@dylanpfirn

Describe the bug

When using an OpenAI-compatible provider via plain llm config (api_key + model + base_url) and specifying model_tokens, the request fails because model_tokens is forwarded to the OpenAI client and ends up as an API request parameter:

TypeError: Completions.create() got an unexpected keyword argument 'model_tokens'. Did you mean 'max_tokens'?

model_tokens is meant to be consumed by ScrapeGraphAI (to size chunking / context), not passed through to the model client.

Root cause

In scrapegraphai/graphs/abstract_graph.py, _create_llm() reads model_tokens but never pops it out of llm_params on the standard path:

https://github.com/ScrapeGraphAI/Scrapegraph-ai/blob/main/scrapegraphai/graphs/abstract_graph.py#L207-L222

if llm_params.get("model_tokens", None) is None:
    ...
    self.model_token = 8192
else:
    self.model_token = llm_params["model_tokens"]   # read, but NOT popped

llm_params (still containing model_tokens) is then splatted straight into init_chat_model(**llm_params):

https://github.com/ScrapeGraphAI/Scrapegraph-ai/blob/main/scrapegraphai/graphs/abstract_graph.py#L239-L241

For a ChatOpenAI client the unknown model_tokens key is treated as a model kwarg and sent to the chat-completions API, which rejects it.

Note the model_instance path (L148-L153) is unaffected because it reads model_tokens and returns early, so the key never reaches a client — which is why the documented model_instance workaround works.

To reproduce

from scrapegraphai.graphs import SmartScraperGraph

graph_config = {
    "llm": {
        "api_key": "<key>",
        "model": "openai/gpt-4o-mini",          # any openai-compatible model
        "base_url": "https://<any-openai-compatible-endpoint>/v1",
        "model_tokens": 128000,                  # <-- triggers the bug
    },
}

SmartScraperGraph(
    prompt="Summarize this page",
    source="https://example.com",
    config=graph_config,
).run()

Result: TypeError: Completions.create() got an unexpected keyword argument 'model_tokens'.

Expected behavior

model_tokens should be consumed by ScrapeGraphAI and not forwarded to the underlying model client, regardless of whether the LLM is created from plain config or from a model_instance.

Suggested fix

Pop model_tokens when reading it so it isn't forwarded:

if llm_params.get("model_tokens", None) is None:
    try:
        self.model_token = models_tokens[llm_params["model_provider"]][llm_params["model"]]
    except KeyError:
        logger.warning(...)
        self.model_token = 8192
else:
    self.model_token = llm_params["model_tokens"]
llm_params.pop("model_tokens", None)   # <-- ensure it never reaches the client

Workaround

Build the client yourself and pass it via model_instance, which consumes model_tokens and returns before it can leak:

from langchain_openai import ChatOpenAI

llm = ChatOpenAI(model="...", api_key="...", base_url="...")
graph_config = {"llm": {"model_instance": llm, "model_tokens": 128000}}

Environment

  • scrapegraphai: 2.1.4
  • Python: 3.13.5
  • OS: macOS (arm64)
  • Provider: OpenAI-compatible endpoint (Cloudflare AI Gateway /compat), reproducible with any OpenAI-compatible base_url.

Activity

  1. dosubot commented on Jul 8, 2026

    @dosubot

    Hi @dylanpfirn! I'm Dosu and I'm helping the ScrapeGraphAI, Inc team.

    Your analysis is spot-on. I can confirm that model_tokens is never popped from llm_params on the standard init_chat_model path [1]. Only rate_limit, temperature (conditionally for Bedrock), and model_provider (for special providers) are explicitly removed before the params are splatted into the client constructor.

    Interestingly, PR #1084 (Atlas Cloud provider integration) already identified and applied exactly the fix pattern you suggest — llm_params.pop("model_tokens", None) before provider instantiation — but only for that specific provider path [2]. It was not retroactively applied to the general init_chat_model path, which is why the bug persists for plain OpenAI-compatible configs.

    Your suggested fix (adding llm_params.pop("model_tokens", None) right after reading the value around line 222) is the correct and minimal approach, and is consistent with the pattern already established in the codebase.

    To reply, just mention @dosu.


    Docs are dead. Just use Dosu.

    Leave Feedback Ask Dosu about Scrapegraph-ai Share Dosu with your team

  2. rehan243 commented on Jul 8, 2026

    @rehan243

    Ran into something similar with LangChain's ChatOpenAI wrapper, where I was passing custom kwargs that ended up getting sent to the OpenAI API. The error message TypeError: Completions.create() got an unexpected keyword argument 'model_tokens' is super familiar - that's exactly what I got when I accidentally passed max_retries as a model kwarg. I've found that it's usually a good idea to explicitly pop out any kwargs that are meant for internal consumption, like model_tokens here, before splatting the rest into the client init. In this case, it's clear that model_tokens is being read but not removed from llm_params before being passed to init_chat_model. I think adding a simple llm_params.pop('model_tokens', None) after reading the value should fix the issue. I've seen this pattern work well with other libraries like Hugging Face Transformers, where you need to separate out config values meant for the model from those meant for your own logic.

  3. github-actions commented on Jul 8, 2026

    @github-actions

    🎉 This issue has been resolved in version 2.1.5 🎉

    The release is available on:

    Your semantic-release bot 📦🚀

  4. github-actions commented on Aug 19, 2026

    @github-actions

    🎉 This issue has been resolved in version 2.2.0-beta.6 🎉

    The release is available on:

    Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions