Skip to content

fix(array): reject unknown keys in ArrayConfig.from_dict - #4414

Merged
d-v-b merged 2 commits into
zarr-developers:mainfrom
d-v-b:fix/array-config-unknown-keys
Sep 26, 2026
Merged

d-v-b merged 2 commits into
zarr-developers:mainfrom
d-v-b:fix/array-config-unknown-keys

Conversation

@d-v-b

@d-v-b d-v-b commented Sep 25, 2026

Copy link
Copy Markdown
Contributor

🤖 AI text below 🤖

ArrayConfig.from_dict read only the keys it models and silently ignored the rest. Every entry point that takes an array config goes through it (create_array, create, open_array, Group.create_array, ...), so a misspelled key was accepted and had no effect:

zarr.create_array({}, shape=(4,), dtype="uint8", config={"write_empty_chunk": True})
# succeeds on main; write_empty_chunks is still False

Array.with_config builds the config with ArrayConfig(**...), and already raised TypeError for the same key, so the outcome depended on the entry point.

from_dict now raises:

TypeError: Unknown array config keys: ['write_empty_chunk']. Valid keys are ['order', 'write_empty_chunks', 'read_missing_chunks', 'sharding_coalesce_max_gap_bytes', 'sharding_coalesce_max_bytes'].

This is a behaviour change: code that passed extra keys in config now fails loudly instead of having them silently ignored.

The agent split this out of #4408, where routing config through the array constructor exposed it.

Tests

  • test_array_config_from_dict: partial and full dicts take the given keys and fill the rest from the global configuration.
  • test_array_config_unknown_key: the one error case, through from_dict, create_array and create. All three fail on main.

The full test suite passes locally, and so does mypy.

🤖 Generated with Claude Code

from_dict read only the keys it models and silently ignored the rest,
so create_array(config={"nope": 1}) succeeded and a misspelled key such
as "write_empty_chunk" had no effect. with_config, which builds the
config with ArrayConfig(**...), already raised for the same key. Raise
a TypeError naming the unknown keys and the valid ones.

Assisted-by: ClaudeCode:claude-opus-5-5
Assisted-by: ClaudeCode:claude-opus-5-5
@github-actions github-actions Bot added needs release notes Automatically applied to PRs which haven't added release notes and removed needs release notes Automatically applied to PRs which haven't added release notes labels Sep 25, 2026
d-v-b added a commit to d-v-b/zarr-python that referenced this pull request Sep 25, 2026
Rejecting unknown config keys changes behaviour for every entry point
that takes a config, so it has its own PR. Until it lands, an unknown
key passed to open_array is ignored on both branches, as it is for
create_array on main.

Assisted-by: ClaudeCode:claude-opus-5-5
@codecov

codecov Bot commented Sep 25, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 94.37%. Comparing base (f58644a) to head (5785153).

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #4414   +/-   ##
=======================================
  Coverage   94.37%   94.37%           
=======================================
  Files          93       93           
  Lines       13171    13174    +3     
=======================================
+ Hits        12430    12433    +3     
  Misses        741      741           
Files with missing lines Coverage Δ
src/zarr/core/array_spec.py 100.00% <100.00%> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@d-v-b
d-v-b marked this pull request as ready for review September 26, 2026 17:06
@d-v-b
d-v-b merged commit 4aeac75 into zarr-developers:main Sep 26, 2026
39 checks passed
d-v-b added a commit to d-v-b/zarr-python that referenced this pull request Sep 30, 2026
Array.open took config as its second positional parameter while
AsyncArray.open took zarr_format there, so a positional second argument
meant different things on the two classes. Both now take config by
keyword only; no caller passed it positionally.

An unknown config key is rejected on both the open and create branches
of open_array now that zarr-developers#4414 has merged, and a test pins that.

Assisted-by: ClaudeCode:claude-fable-5-1
d-v-b added a commit that referenced this pull request Oct 26, 2026
* fix(api): apply config when open_array opens an existing array

open_array forwarded **kwargs, including config, only to create() in the
branch that creates a missing array. Opening an existing array dropped
config and ran with the global defaults. Apply it with with_config().

Assisted-by: ClaudeCode:claude-opus-5-5

* docs(changes): name the fragment for #4408

Assisted-by: ClaudeCode:claude-opus-5-5

* refactor(api): make config a named parameter of open and open_array

config was read from **kwargs, which is how the existing-array branch
came to drop it. It is now a named parameter of zarr.open and
open_array (sync and async), passed explicitly to every branch.
AsyncArray.open and Array.open take a config, so an opened array is
built once with it instead of being rebuilt with with_config().

zarr.open raises a TypeError naming the problem when config is given
for a node that resolves to a group, instead of open_group's
"unexpected keyword argument".

ArrayConfig.from_dict now rejects unknown keys. Passing config through
the constructor exposed that it silently ignored them, so an unknown
key raised in with_config() but not in create_array().

Assisted-by: ClaudeCode:claude-opus-5-5

* refactor: move ArrayConfig.from_dict strictness to #4414

Rejecting unknown config keys changes behaviour for every entry point
that takes a config, so it has its own PR. Until it lands, an unknown
key passed to open_array is ignored on both branches, as it is for
create_array on main.

Assisted-by: ClaudeCode:claude-opus-5-5

* fix(array): make config keyword-only on Array.open and AsyncArray.open

Array.open took config as its second positional parameter while
AsyncArray.open took zarr_format there, so a positional second argument
meant different things on the two classes. Both now take config by
keyword only; no caller passed it positionally.

An unknown config key is rejected on both the open and create branches
of open_array now that #4414 has merged, and a test pins that.

Assisted-by: ClaudeCode:claude-fable-5-1

* test: expect the group config TypeError from zarr.open in mode w

Assisted-by: ClaudeCode:claude-opus-5.5
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.

1 participant