Skip to content

Fix type: [A, B] + values: [...] raising IncompatibleOptionValues at definition time#2814

Open
ericproulx wants to merge 1 commit into
masterfrom
fix-multiple-type-values-check
Open

Fix type: [A, B] + values: [...] raising IncompatibleOptionValues at definition time#2814
ericproulx wants to merge 1 commit into
masterfrom
fix-multiple-type-values-check

Conversation

@ericproulx

Copy link
Copy Markdown
Contributor

Summary

Sibling of #2812 (fixed by #2813): a multiple-type declaration combined with values: or except_values: raises Grape::Exceptions::IncompatibleOptionValues at definition time on master, so the API class fails to load. All of these were accepted in 3.2.1 (verified against the v3.2.1 tag):

Declaration 3.2.1 master (before this PR)
type: [Integer, String], values: [1, 2] OK raises at definition time
type: [Integer, String], except_values: [3] OK raises at definition time
type: Set[Integer, String], values: [1] OK raises at definition time
types: [Integer, String], values: [1] OK OK (raw-list path, unaffected)

The raised message even has a blank type name (type: is incompatible with values: [1, 2]), which hints at the root cause below.

Root cause

Same clobbering family as #2812. ValidationsSpec#parse_coerce stores a Types::VariantCollectionCoercer instance in @coerce_type when Types.multiple?(type) is true — correct for runtime coercion and for documentation (to_s"Array[Integer, String]"), but the definition-time coherence check also reads @coerce_type:

value_types.all?(coerce_type)  # all? with a pattern uses ===

VariantCollectionCoercer doesn't define ===, so Object#=== (identity) matches nothing and the check can never pass.

In 3.2.1 the two roles were separate: infer_coercion returned the raw declared type ([Integer, String]) for validate_value_coercion/guess_coerce_type/docs, while the wrapper went into validations[:coerce] for the runtime validator. The ValidationsSpec refactor merged both roles into @coerce_type; #2813 un-merged the values-guessed-type leg but not this one.

Fix

Mirrors #2813's isolation strategy:

  • ValidationsSpec gains a private declared_coerce_type that unwraps a VariantCollectionCoercer back to the declared member-type list, and guess_coerce_type/validate_value_coercion now receive that. @coerce_type is untouched, so coerce_options (runtime) and ParamsDocumentation (renders "Array[Integer, String]") keep their current behavior.
  • VariantCollectionCoercer gains an attr_reader :types so the declared list is recoverable from the wrapper.

The restored check semantics are exactly 3.2.1's: the declared list is Enumerable, so the existing coerce_type = coerce_type.first if coerce_type.is_a?(Enumerable) line validates values against the first declared member type. That means type: [Integer, String], values: %w[active] still raises — quirky, but it is the historical contract, and this PR deliberately restores rather than redesigns it.

Tests

  • spec/grape/validations/params_scope_spec.rb: six integration cases — values:, except_values:, and Set[...] accepted at definition time; array of allowed values accepted at request time; disallowed value rejected with does not have a valid value; incompatible values list still raises IncompatibleOptionValues.
  • spec/grape/validations/validations_spec_spec.rb: unit coverage that the wrapper stays in coerce_type while the values check passes, and that an incompatible list still raises.

Full suite: 2375 examples, 0 failures. RuboCop clean.

🤖 Generated with Claude Code

…definition time

Sibling of #2812: parse_coerce stores a VariantCollectionCoercer in
@coerce_type for a multiple-type declaration, and the values coherence
check received the wrapper instead of the declared list — Object#===
matches nothing, so any type: [A, B] + values:/except_values: param
raised at definition time (accepted in 3.2.1). Feed the check the
declared member types; the wrapper stays in place for runtime coercion
and documentation.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@ericproulx
ericproulx force-pushed the fix-multiple-type-values-check branch from 9b43051 to e5a88cc Compare July 25, 2026 18:11
@github-actions

github-actions Bot commented Jul 25, 2026

Copy link
Copy Markdown

Danger Report

No issues found.

View run

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