Skip to content

fix(odata): type an external action's return value and its parameters - #381

Merged
ako merged 1 commit into
mainfrom
claude/mxbuild-diagnostics-spike-emta6h
Sep 3, 2026
Merged

fix(odata): type an external action's return value and its parameters#381
ako merged 1 commit into
mainfrom
claude/mxbuild-diagnostics-spike-emta6h

Conversation

@ako

@ako ako commented Sep 3, 2026

Copy link
Copy Markdown
Owner

A call external action against a consumed OData service was written with neither the result variable's type nor its parameters' types. Mendix reported CE7269 and CE7252, and re-running CREATE OR MODIFY EXTERNAL ENTITIES never cleared them.

Fixes mendixlabs#1020.

Why the reported remedy could never work

Both codes are defined on CallExternalAction.cs — extracted from Mendix 11.13's own Mendix.Modeler.Texts.dll:

Code Symbol Text
CE7252 ACTION_PARAMETERS_UNALIGNED "The parameters for remote action '{ACTION}' have changed."
CE7269 ACTION_RETURN_TYPE_UNALIGNED "The return type for remote action '{ACTION}' has changed."

They are raised by the microflow activity, not by the entity. CREATE OR MODIFY EXTERNAL ENTITIES writes entities, so it reports success and changes nothing relevant — which is exactly what the reporter observed and reasonably read as a linkage bug.

Two omissions of the same shape

Each is a DataTypes$ sub-document that was never written:

CE7269 — entity returns. edmReturnTypeToKind mapped only EDM primitives and returned "" for everything else, self-documented as "Complex / collection / entity-typed returns aren't yet mapped". An action returning an entity got no VariableDataType at all. It now resolves to DataTypes$ObjectType / DataTypes$ListType naming the external entity imported for that type — matching on RemoteServiceName + RemoteEntityName, the same linkage the entity import writes.

CE7252 — parameters. ExternalActionParameterMapping.ParameterType was never written, though generated/metamodel declares it without omitempty. This is larger than the report describes: a call with any parameter, of any type, produced CE7252 plus one CE0117 "Error(s) in expression" per argument — an argument cannot be type-checked against an untyped parameter. I found it by testing the missing-mandatory-property hypothesis a second time after it explained the first half.

The catalog fix, and why the report's evidence was misleading

external_entities catalogued only Rest$ODataRemoteEntitySource, skipping every Rest$ODataEntityTypeSource — what CREATE EXTERNAL ENTITIES writes for any type the contract gives no entity set: derived, abstract, contained, and an action's parameter and return types.

The consequence was worse than the under-count. contract_entities.UsedByExternalEntity is filled by joining that table on RemoteName, so for exactly those entities the column was structurally always empty — it read as "linked to nothing" whether or not the import had worked. That column is what the issue was diagnosed from. Both sources are catalogued now, and the reporter's query resolves (Airport → Ext.Airport).

Worth noting generally: when a report cites one of our own derived columns as evidence, check the column can be non-empty for that case before believing it.

Verification

No $metadata fixture in the repo declares an action at all, so this path had no end-to-end coverage. I served a contract from python3 -m http.server on loopback and pointed MetadataUrl at it, which makes the whole consumed-OData path testable locally.

Measured on Mendix 11.13, three action shapes, mx check after each:

shape before after
no parameters, entity return CE7269 0 errors
one string parameter CE7252 + 1× CE0117 0 errors
two double parameters CE7252 + 2× CE0117 0 errors

Controls: reverting the return resolver reproduces CE7269 verbatim on the same app; removing the Object/List writer cases makes the unit tests report DataTypes$VoidType, which is precisely the reported symptom.

Unit tests cover the writers on both engines (the modelsdk one asserts on the encoded document, so Entity and ParameterType are checked as stored keys rather than Go fields), the type-name normalisation, the call walker, and the catalog join — the last with a control proving an unimported type still reads as unlinked, so the join cannot pass by populating everything.

make build, full go test ./..., make lint-go, make check-mdl (463 PASS, exit 0) and make check-findings all green.

Also in this PR

check --references now resolves the call against the cached contract, so an unknown action, an argument the action does not declare, a declared parameter left unsupplied, or an entity return whose entity has not been imported are reported with the statement that fixes them rather than surfacing a build later.

Two constraints learned while building the fixture and worth knowing: Mendix's call external action takes OData Actions only, not Functions (CE7251), and an unbound action needs an <ActionImport> in the EntityContainer or it is not part of the service's callable surface at all.

Note on branching

PR #374 merged while this was in progress, so this branch was restarted from current main with rebase --onto and everything above was re-measured against that base. This commit is not part of #374.

🤖 Generated with Claude Code

https://claude.ai/code/session_01JXnEgoc2NQP1Y2TWMCMXC4


Generated by Claude Code

A `call external action` was written with neither the result variable's
type nor its parameters' types, so Mendix reported CE7269 ("the return
type for remote action '<x>' has changed") and CE7252 ("the parameters
... have changed"), and re-running CREATE OR MODIFY EXTERNAL ENTITIES
never cleared them.

It never could. Both codes are defined on CallExternalAction.cs
(extracted from Mendix.Modeler.Texts.dll, 11.13): they are raised by the
microflow ACTIVITY, not by the entity. That is what made the reported
remedy the wrong lever, and it cost the reporter a debugging session.

Two omissions of the same shape, each a DataTypes$ sub-document that was
never written:

  - The return-type resolver mapped only EDM primitives and returned ""
    for anything else, so an action returning an entity (or a collection
    of them) got no VariableDataType at all. It now resolves to
    DataTypes$ObjectType / DataTypes$ListType naming the external entity
    imported for that type -- the same linkage the entity import writes.

  - ExternalActionParameterMapping.ParameterType was never written,
    though generated/metamodel declares it WITHOUT omitempty. Measured: a
    call with ANY parameter, of any type, produced CE7252 plus one CE0117
    "Error(s) in expression" per argument, because an argument cannot be
    type-checked against an untyped parameter.

Measured on 11.13 against a contract with three action shapes: before, a
no-parameter entity return was CE7269, a one-string-parameter call was
CE7252 + 1x CE0117, and a two-parameter call CE7252 + 2x CE0117; after,
all three build at 0 errors. Reverting the return resolver reproduces
CE7269 verbatim.

`check --references` now resolves the call against the cached contract
too, so an unknown action, an undeclared argument, a missing parameter,
or an entity return whose entity has not been imported are reported with
the statement that fixes them.

Also: the catalog listed only entities stored as
Rest$ODataRemoteEntitySource, skipping every Rest$ODataEntityTypeSource
-- what CREATE EXTERNAL ENTITIES writes for any type the contract gives
no entity set, including an action's parameter and return types. The
consequence was worse than the under-count: contract_entities.
UsedByExternalEntity is filled by joining that table on RemoteName, so
for exactly those entities the column was structurally always empty and
read as "linked to nothing" whether or not the import had worked. That
column is the evidence the report was diagnosed from.

Fixes mendixlabs#1020

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JXnEgoc2NQP1Y2TWMCMXC4
@ako
ako force-pushed the claude/mxbuild-diagnostics-spike-emta6h branch from 76795bb to c6b5fc2 Compare September 3, 2026 21:04
@ako
ako merged commit 4e6674d into main Sep 3, 2026
13 of 14 checks passed
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.

CREATE OR MODIFY EXTERNAL ENTITIES FROM does not link action parameter/response entities to OData contract, leaving CE7252/CE7269 unresolvable via CLI

2 participants