openai/openai-python · error · ValueError

Expected a non-empty value for `thread_id` but received {thr

Error message

Expected a non-empty value for `thread_id` but received {thread_id!r}

What it means

client.beta.threads.messages.create() requires a non-empty thread_id because it is a path parameter for POST /threads/{thread_id}/messages. The SDK validates this client-side and raises ValueError before making any HTTP request, since an empty id would build a malformed URL.

Source

Thrown at src/openai/resources/beta/threads/messages.py:98

          attachments: A list of files attached to the message, and the tools they should be added to.

          metadata: Set of 16 key-value pairs that can be attached to an object. This can be useful
              for storing additional information about the object in a structured format, and
              querying for objects via API or the dashboard.

              Keys are strings with a maximum length of 64 characters. Values are strings with
              a maximum length of 512 characters.

          extra_headers: Send extra headers

          extra_query: Add additional query parameters to the request

          extra_body: Add additional JSON properties to the request

          timeout: Override the client-level default timeout for this request, in seconds
        """
        if not thread_id:
            raise ValueError(f"Expected a non-empty value for `thread_id` but received {thread_id!r}")
        extra_headers = {"OpenAI-Beta": "assistants=v2", **(extra_headers or {})}
        return self._post(
            path_template("/threads/{thread_id}/messages", thread_id=thread_id),
            body=maybe_transform(
                {
                    "content": content,
                    "role": role,
                    "attachments": attachments,
                    "metadata": metadata,
                },
                message_create_params.MessageCreateParams,
            ),
            options=make_request_options(
                extra_headers=extra_headers,
                extra_query=extra_query,
                extra_body=extra_body,
                timeout=timeout,
                security={"bearer_auth": True},

View on GitHub (pinned to 9917c6e28e)

Solutions

  1. Create the thread first and pass its id: thread = client.beta.threads.create(); client.beta.threads.messages.create(thread_id=thread.id, ...)
  2. Verify the variable actually holds a string id, not an object or None
  3. Validate ids from external input before calling the API

Example fix

# before
client.beta.threads.messages.create(thread_id="", content="hi", role="user")
# after
thread = client.beta.threads.create()
client.beta.threads.messages.create(thread_id=thread.id, content="hi", role="user")
Defensive patterns

Strategy: validation

Validate before calling

if not thread_id:
    raise ValueError("thread_id is required; create the thread first")
client.beta.threads.messages.create(thread_id=thread_id, role="user", content="hi")

Type guard

def has_thread_id(t: object) -> bool:
    return isinstance(t, str) and bool(t.strip())

Prevention

When it happens

Trigger: Calling client.beta.threads.messages.create(thread_id="", ...) or passing None/an unassigned variable as thread_id.

Common situations: Creating a message before creating the thread (no id yet), storing the wrong field (passing the Thread object or the message instead of thread.id), or ids loaded from empty config/env values.

Understand the failure class

Background: Missing required parameter errors: what 'X is required' and 'the required X param is missing' mean, and how to fix them — this error's family across 27 libraries.

Related errors


AI-assisted analysis of openai/openai-python@9917c6e28e (2026-08-28). Data as JSON: /api/errors/440b1f2436776cf4. Report an issue: GitHub.