Skip to content

fix: ChoicesFromFiles snake_case to camelCase#393

Open
bramj wants to merge 1 commit into
mainfrom
fix-choices-from-file-issue
Open

fix: ChoicesFromFiles snake_case to camelCase#393
bramj wants to merge 1 commit into
mainfrom
fix-choices-from-file-issue

Conversation

@bramj
Copy link
Copy Markdown
Contributor

@bramj bramj commented May 29, 2026

Issue: Pushing a pipeline with dynamic parameters with the CLI fails.

image (22)

Sorry for the raw Claude fix, didn't review the code, but I tested and it does fix the issue

Claude message:

This is a bug in the SDK's CLI upload path.

Root cause

The server's GraphQL ParameterInput type expects the field name choicesFromFile (camelCase). The SDK was sending choices_from_file (snake_case), so the server rejected it — exactly what the error said: "Field 'choices_from_file' is not defined by type 'ParameterInput'. Did you mean 'choicesFromFile'?"

Why it only broke now: upload_pipeline (in openhexa/cli/api.py) passes Parameter.to_dict() straight through as the GraphQL input. Every previous parameter field was a single word (code, type, name, required, multiple, directory…), so snake_case and camelCase happened to be identical. choices_from_file, added in the recent dynamic-choices feature (#385), is the first multi-word field — so it's the first mismatch.

Fix

I added a small boundary serializer that renames the key only when sending to GraphQL, in openhexa/cli/api.py. I deliberately left Parameter.to_dict() untouched — it keeps snake_case as its internal spec convention (the AST-construction code and ~22 tests in tests/test_choices.py rely on that), so the camelCase concern lives only where it belongs: the GraphQL call.

Verification

  • Executed the helper: ChoicesFromFile("regions.csv", column="code") now serializes to {"choicesFromFile": {"format": None, "path": "regions.csv", "column": "code"}}, snake key gone, nested values intact. Parameters without dynamic choices don't get the key.
  • to_dict() still returns snake_case (internal convention preserved).
  • tests/test_choices.py → 22 passed; tests/test_cli.py (upload/pipeline/parameter) → 18 passed; ruff check clean.

One side note: the SDK's bundled schema (openhexa/graphql/schema.generated.graphql) doesn't yet contain the choicesFromFile field at all — it lags the server. That doesn't block the push (validation is server-side), but it's worth refreshing the bundled schema in a follow-up so
the SDK's breaking-change detection stays accurate.

Re-run openhexa pipelines push and it should import cleanly now.

This is a bug in the SDK's CLI upload path.

Root cause

The server's GraphQL ParameterInput type expects the field name choicesFromFile (camelCase). The SDK was sending choices_from_file (snake_case), so the server rejected it — exactly what the error said: "Field 'choices_from_file' is not defined by type 'ParameterInput'. Did you
mean 'choicesFromFile'?"

Why it only broke now: upload_pipeline (in openhexa/cli/api.py) passes Parameter.to_dict() straight through as the GraphQL input. Every previous parameter field was a single word (code, type, name, required, multiple, directory…), so snake_case and camelCase happened to be
identical. choices_from_file, added in the recent dynamic-choices feature (#385), is the first multi-word field — so it's the first mismatch.

Fix

I added a small boundary serializer that renames the key only when sending to GraphQL, in openhexa/cli/api.py. I deliberately left Parameter.to_dict() untouched — it keeps snake_case as its internal spec convention (the AST-construction code and ~22 tests in tests/test_choices.py
rely on that), so the camelCase concern lives only where it belongs: the GraphQL call.

Verification

- Executed the helper: ChoicesFromFile("regions.csv", column="code") now serializes to {"choicesFromFile": {"format": None, "path": "regions.csv", "column": "code"}}, snake key gone, nested values intact. Parameters without dynamic choices don't get the key.
- to_dict() still returns snake_case (internal convention preserved).
- tests/test_choices.py → 22 passed; tests/test_cli.py (upload/pipeline/parameter) → 18 passed; ruff check clean.

One side note: the SDK's bundled schema (openhexa/graphql/schema.generated.graphql) doesn't yet contain the choicesFromFile field at all — it lags the server. That doesn't block the push (validation is server-side), but it's worth refreshing the bundled schema in a follow-up so
  the SDK's breaking-change detection stays accurate.

Re-run openhexa pipelines push and it should import cleanly now.
@bramj bramj requested a review from mrivar May 29, 2026 11:25
Copy link
Copy Markdown
Contributor

@mrivar mrivar left a comment

Choose a reason for hiding this comment

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

That's interesting, it is a bit annoying having that double format of snake_case + camelCase being different.
Thanks for the fix!

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.

2 participants