Skip to content

Report unsupported python/pydantic language naming convention - #3743

Closed
ATX24 wants to merge 3 commits into
canaryfrom
cursor/pydantic-naming-convention-error-886c
Closed

ATX24 wants to merge 3 commits into
canaryfrom
cursor/pydantic-naming-convention-error-886c

Conversation

@ATX24

@ATX24 ATX24 commented Jun 11, 2026 •

Copy link
Copy Markdown
Contributor

Pull Request Template

Thanks for taking the time to fill out this pull request!

Issue Reference

  • This PR fixes/closes #[issue number]

The error

The following BAML crashed before this change when generated with the compiler2 CLI:

generator target {
  output_type "python/pydantic"
  output_dir "../"
  default_client_mode "sync"
  naming_convention "language"
}

function main() -> string {
  "hello"
}

Pre-fix reproduction with cargo run -p baml_cli --bin baml-cli -- generate --from /tmp/tmp.WSMWmSKIpB exited through Rust panic while running under Cargo:

warning: using the internal BAML toolchain binary directly is not recommended. Use `baml` instead.
     Loading /tmp/tmp.WSMWmSKIpB/baml_src/main.baml
    Checking 1 file(s)
   Resolving generator blocks
   Compiling 1 file(s)
  Generating target

thread 'main' (32002) panicked at sdks/python/rust/sdkgen_python_pydantic2/src/lib.rs:141:5:
sdkgen_python_pydantic2 only supports naming_convention = PreserveCase (got language)
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

Root cause

baml_language/crates/baml_cli/src/generate.rs::discover_generators parsed naming_convention with a target-agnostic expected-value list that accepted and advertised both "preserve-case" and "language" for every generator. The python/pydantic backend in baml_language/sdks/python/rust/sdkgen_python_pydantic2/src/lib.rs::to_source_code_internal only supports PreserveCase and asserted when it received Language, so CLI validation let an unsupported value reach a panic path.

The SDK test harness in baml_language/sdk_tests/harness_setup/src/python_pydantic2.rs::codegen_fixture also called that backend directly and needed to handle the new fallible result instead of only catching panics.

The fix

  • Make generator validation target-aware for python/pydantic and python/pydantic/v1, so missing naming_convention guidance lists only "preserve-case" for those targets.
  • Reject parsed naming_convention "language" for python/pydantic targets with DiagnosticId::InvalidGeneratorPropertyValue and a primary span on the offending generator config item.
  • Make the python sdkgen entrypoints return a typed UnsupportedNamingConvention error instead of asserting internally.
  • Update the python SDK test harness to record fallible codegen errors.
  • Add CLI e2e tests for the unsupported value and corrected missing-property guidance, plus a sdkgen unit test for the typed error.

Verification

Pre-fix reproduction was run first and produced the panic shown above.

Post-fix manual reproduction:

$ ./target/debug/baml-cli generate --from /tmp/tmp.prkLQQ52G5
EXIT=4
warning: using the internal BAML toolchain binary directly is not recommended. Use `baml` instead.
     Loading /tmp/tmp.prkLQQ52G5/baml_src/main.baml
    Checking 1 file(s)
   Resolving generator blocks
error: invalid value `language` for `naming_convention` on generator `target` with output_type `python/pydantic` (expected "preserve-case")
   ╭─[ main.baml:4:29 ]
   │
 4 │ ╭─▶   default_client_mode "sync"
 5 │ ├─▶   naming_convention "language"
   │ │                                    
   │ ╰──────────────────────────────────── `language` is not supported by this generator
   │     
   │     Note: Error code: E0019
───╯

Commands run from baml_language/:

cargo test -p sdkgen_python_pydantic2 language_naming_convention_returns_error
# 1 passed

cargo test -p baml_cli --test exit_code_e2e generate_python_pydantic
# 2 passed

cargo test --lib
# Failed only because explicit --lib forces bridge_nodejs into a standalone lib-test link mode;
# sdks/nodejs/bridge_nodejs/Cargo.toml documents that this cannot link N-API symbols.

cargo test --lib --workspace --exclude bridge_nodejs --exclude bridge_python
# Passed. bridge_python is the analogous cdylib bridge and failed standalone lib-test linking with missing libpython3.12.

mise trust /workspace/baml_language/mise.toml
./sdk_tests/crates/typescript_node/setup.sh
cargo test
# Passed full workspace suite after SDK fixture setup.

cargo fmt --all --check
# Passed

cargo clippy --all-targets -- -D warnings
# Passed

Snapshot tests were covered by the full cargo test; there were no snapshot updates to accept.

CodeRabbit:

curl -fsSL https://cli.coderabbit.ai/install.sh | sh
# Installed coderabbit 0.6.0 successfully.
CODERABBIT_API_KEY is not set

Because CODERABBIT_API_KEY is missing from this environment, I could not authenticate or run coderabbit review --plain --base canary.

Environment note: the repository setup script installed the main mise-managed toolchain but exited while installing cargo-shear@latest with cargo exit code 101 in this environment. I continued after trusting baml_language/mise.toml and running the SDK setup needed by plain cargo test.

Changes

See The fix above.

Testing

  • Unit tests added/updated
  • Manual testing performed
  • Tested in linux 6.1.147 Cursor Cloud environment

Screenshots

N/A

PR Checklist

  • I have read and followed the contributing guidelines
  • My code follows the style guidelines of this project
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation (not needed; validator/tests only)
  • My changes generate no new warnings

Additional Notes

All code changes are inside baml_language/. The legacy engine/ directory was not modified.

Open in Web Open in Cursor 

Summary by CodeRabbit

  • Bug Fixes
    • Generators now fail with clear, non-panic errors when an unsupported naming convention is used; commands return the appropriate exit code.
  • Improvements
    • Validation and diagnostics for generator naming_convention were tightened to only allow the supported option and to surface precise error locations.
  • Tests
    • End-to-end tests added to cover naming-convention validation for multiple generator targets.

@vercel

vercel Bot commented Jun 11, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
beps Ready Ready Preview, Comment Jun 12, 2026 7:49pm
promptfiddle Ready Ready Preview, Comment Jun 12, 2026 7:49pm
promptfiddle2 Ready Ready Preview, Comment Jun 12, 2026 7:49pm

Request Review

@coderabbitai

coderabbitai Bot commented Jun 11, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 925789a0-1961-4b81-ad6a-81a1edc1199f

📥 Commits

Reviewing files that changed from the base of the PR and between 50d79da and 6bfeb4c.

📒 Files selected for processing (4)
  • baml_language/crates/baml_cli/src/generate.rs
  • baml_language/crates/baml_cli/tests/exit_code_e2e.rs
  • baml_language/sdk_tests/harness_setup/src/python_pydantic2.rs
  • baml_language/sdks/python/rust/sdkgen_python_pydantic2/src/lib.rs
🚧 Files skipped from review as they are similar to previous changes (2)
  • baml_language/sdk_tests/harness_setup/src/python_pydantic2.rs
  • baml_language/sdks/python/rust/sdkgen_python_pydantic2/src/lib.rs

📝 Walkthrough

Walkthrough

Adds a typed UnsupportedNamingConvention error and Result-returning SDK APIs, updates harness and CLI to handle and report codegen errors, validates generator naming_convention during discovery (rejecting language), and adds e2e tests for invalid or missing naming_convention.

Changes

Python/Pydantic naming convention enforcement

Layer / File(s) Summary
SDK error type and public API signatures
baml_language/sdks/python/rust/sdkgen_python_pydantic2/src/lib.rs
Introduces UnsupportedNamingConvention and changes to_source_code / to_source_code_with_bytecode to return Result<HashMap<PathBuf,String>, UnsupportedNamingConvention>.
SDK implementation with error handling & tests
baml_language/sdks/python/rust/sdkgen_python_pydantic2/src/lib.rs
Replaces assert-based panic with Err(UnsupportedNamingConvention { ... }) when naming convention != PreserveCase; wraps successful output in Ok(out); updates tests to unwrap and adds a test for Language.
Test harness nested-Result handling
baml_language/sdk_tests/harness_setup/src/python_pydantic2.rs
Matches Ok(Ok(output)) for success, adds Ok(Err(e)) arm to record a "codegen" diagnostic when generation returns an error, retains panic (Err(_)) handling.
CLI naming-convention validation and span helpers
baml_language/crates/baml_cli/src/generate.rs
Change expected text for required naming_convention to preserve-case; add validate_target_naming_convention to emit InvalidGeneratorPropertyValue for Language with primary span from generator_config_item_span; call validator during discovery and skip invalid generators; map bytecode-backed codegen errors to anyhow!(e) in GenerateArgs::run.
CLI end-to-end naming_convention tests
baml_language/crates/baml_cli/tests/exit_code_e2e.rs
Adds four e2e tests: invalid naming_convention = language and omitted naming_convention for both python/pydantic and typescript/node, asserting exit code 4 and precise structured diagnostics (including (got \language`)` for the invalid-value cases).

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • BoundaryML/baml#3490: Related prior work enforcing naming_convention "preserve-case" during generator discovery and validation.
  • BoundaryML/baml#3604: Adds exit-code e2e tests for generator failures; similar test-area changes.

Poem

🐰 I nibble on code with careful paws,

Typed errors hush the panic's claws.
CLI points to "preserve-case" bright,
Tests hop in to keep things right.
A rabbit cheers: errors handled light.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically summarizes the main change: fixing unsupported python/pydantic language naming convention reporting, which aligns with the core purpose of this PR to replace a panic with proper error diagnostics.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch cursor/pydantic-naming-convention-error-886c

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@vercel
vercel Bot temporarily deployed to Preview – beps June 11, 2026 18:23 Inactive
@github-actions

github-actions Bot commented Jun 11, 2026 •

Copy link
Copy Markdown

⏭️ Performance benchmarks were skipped

Perf benchmarks (CodSpeed) are opt-in on pull requests — they no longer run on every push. They always run automatically after merge to canary/main.

To run them on this PR, do any of the following, then push a commit (or re-run CI):

  • Add RUN_CODSPEED=1 to the PR description, or
  • Include run-perf or /perf in the PR title or any commit message.

@vercel
vercel Bot temporarily deployed to Preview – beps June 11, 2026 18:27 Inactive
@github-actions

github-actions Bot commented Jun 11, 2026 •

Copy link
Copy Markdown

No description provided.

@vercel
vercel Bot temporarily deployed to Preview – promptfiddle2 June 11, 2026 18:33 Inactive
@vercel
vercel Bot temporarily deployed to Preview – promptfiddle June 11, 2026 18:45 Inactive
@ATX24
ATX24 marked this pull request as ready for review June 11, 2026 18:51

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
baml_language/crates/baml_cli/tests/exit_code_e2e.rs (1)

232-276: 💤 Low value

Optional: Remove unnecessary default_client_mode field.

The default_client_mode "sync" field on line 242 is not required for this test and is not part of the tested behavior (naming_convention validation). The existing helper create_project_with_generator (lines 44-54) doesn't include this field. Consider removing it for clarity, or document why it's included if it serves a specific purpose.

♻️ Simplified test fixture
     create_project(
         tmp.path(),
         r#"generator target {
   output_type "python/pydantic"
   output_dir "../"
-  default_client_mode "sync"
   naming_convention "language"
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@baml_language/crates/baml_cli/tests/exit_code_e2e.rs` around lines 232 - 276,
In the test
generate_python_pydantic_language_naming_convention_returns_diagnostic, remove
the unnecessary default_client_mode "sync" field from the generator fixture
created via create_project (it is not required for the naming_convention
validation being tested and differs from the helper
create_project_with_generator); update the generator block passed to
create_project so it only includes the relevant keys (target, output_type,
output_dir, naming_convention) to keep the fixture minimal and consistent with
other tests.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@baml_language/crates/baml_cli/tests/exit_code_e2e.rs`:
- Around line 232-276: In the test
generate_python_pydantic_language_naming_convention_returns_diagnostic, remove
the unnecessary default_client_mode "sync" field from the generator fixture
created via create_project (it is not required for the naming_convention
validation being tested and differs from the helper
create_project_with_generator); update the generator block passed to
create_project so it only includes the relevant keys (target, output_type,
output_dir, naming_convention) to keep the fixture minimal and consistent with
other tests.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 013d2222-ef73-438f-8caf-59428390c83d

📥 Commits

Reviewing files that changed from the base of the PR and between c2789e5 and 50d79da.

📒 Files selected for processing (4)
  • baml_language/crates/baml_cli/src/generate.rs
  • baml_language/crates/baml_cli/tests/exit_code_e2e.rs
  • baml_language/sdk_tests/harness_setup/src/python_pydantic2.rs
  • baml_language/sdks/python/rust/sdkgen_python_pydantic2/src/lib.rs

fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"sdkgen_python_pydantic2 only supports naming_convention = PreserveCase (got {})",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is the final user-facing diagnostic? We should make this more legible

generator python/pydantic requires setting naming_convention preserve-case

Comment on lines +242 to +247
let naming_convention_expected = match output_type {
Some(OutputType::PythonPydantic | OutputType::PythonPydanticV1) => {
r#""preserve-case""#
}
Some(OutputType::TypescriptNode) | None => r#""preserve-case" or "language""#,
};

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

language is never allowed today, i.e. TypescriptNode should have same behavior

}));
match codegen_result {
Ok(output) => {
Ok(Ok(output)) => {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i'm missing something here, why are we going from Result<codegen output, codegen error> to Result<Result<...>, codegen error>?

@vercel
vercel Bot temporarily deployed to Preview – beps June 12, 2026 19:30 Inactive
@vercel
vercel Bot temporarily deployed to Preview – promptfiddle2 June 12, 2026 19:35 Inactive
@vercel
vercel Bot temporarily deployed to Preview – promptfiddle June 12, 2026 19:49 Inactive
@ATX24 ATX24 closed this Jun 15, 2026

This branch was previously deployed

3 inactive deployments
Preview – promptfiddle — 6bfeb4c0 Deployed Jun 12, 2026 by vercel[bot]
Preview – promptfiddle2 — 6bfeb4c0 Deployed Jun 12, 2026 by vercel[bot]
Preview – beps — 6bfeb4c0 Deployed Jun 12, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants