Problem/Motivation

A config entity is available in its own base language, but a strict langCode read says otherwise. On an English site, GET /jsonapi/menu/menu/{uuid}?langCode=en returns 404, and GET /jsonapi/menu/menu?langCode=en omits every menu that has no dedicated en override.

Since #3613823 made langCode the only read selector, a client that uniformly appends it cannot read config entities in the site's own language at all.

The clearest symptom is that the error contradicts itself. The strict miss is thrown on an override-only check, while the error body advertises availability computed as base language plus overrides, so the response reads:

  • {"errors":[{"detail":"The \"en\" translation of the specified resource does not exist. Available translations: en, fr.","meta":{"availableTranslations":["en","fr"]}}]}

The module already defines availability correctly in three other places (availableConfigLangcodes() on both the controller and the access checker, and the ?include= path's membership check). Only two sites, the individual strict-miss gate and the collection filter, use the narrower "has an override" test, and both predate the helper.

This also violates the module's own spec, which defines an available language for config as "a config override or the base config in that language".

Steps to reproduce

  1. Site with en (default) and fr configured, and a menu with an fr config override.
  2. GET /jsonapi/menu/menu/{uuid}?langCode=en404, with a detail that lists en among the available translations.
  3. GET /jsonapi/menu/menu?langCode=en → the menu is missing from the collection.
  4. GET /jsonapi/menu/menu/{uuid}?langCode=fr200, as expected.
  5. GET /jsonapi/node/article/{uuid}?include=node_type&langCode=fr → the node type is correctly reported under meta.omitted, showing the include path already gets this right.

Proposed resolution

Use one definition of config availability everywhere: base language plus overrides.

  • Individual reads: the strict-miss gate tests membership of availableConfigLangcodes() instead of override existence. The guard fails open: when the language manager is not a ConfigurableLanguageManagerInterface the 404 branch is skipped entirely, rather than rejecting everything, matching how the access checker already degrades on a non-multilingual site.
  • Collections: the strict filter loads each candidate and applies the same membership test. The ids are config entity IDs rather than loaded entities, so the filter loads them; the removed Accept-Language arm used the same shape for the same reason.
  • Fallback mode is untouched. With includeFallback=1 a config entity is already served with the requested language's overrides when present and its base values otherwise, which is the config override layer's own fallback.
  • The now-unused configEntityHasOverride() helper is deleted, and both DIVERGENCE(core): comments are reworded from "no override for that language" to "no content in that language (its base language or an override)".
Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

lauriii created an issue. See original summary.

  • lauriii committed 7458a9ba on 1.0.x
    fix: #3614382 A strict langCode read 404s config entities in their own...
lauriii’s picture

Status: Active » Fixed

Now that this issue is closed, review the contribution record.

As a contributor, attribute any organization that helped you, or if you volunteered your own time.

Maintainers, credit people who helped resolve this issue.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.