run --local: attach a file log subscriber so application logs are captured - #39
Merged
Conversation
…tured The runtime-log tee added earlier writes the runtime JVM's stdout/stderr to .mxcli/runtime.log, but a standalone runtime (launched via runtimelauncher.jar) attaches no log subscriber by default — unlike a Studio Pro / m2ee run, which calls create_log_subscriber after start. Mendix application logs flow to log subscribers, not stdout, so microflow LOG output and server-side exception stack traces never reached the file: a page-action error still showed only the generic Mendix dialog with nothing to correlate against. After a successful start (and on every restart's Start, since each fresh JVM starts with no subscriber), attach a "file" log subscriber pointing at the same runtime.log with autosubscribe INFO. max_rotate is 0 so the runtime never renames the file out from under the JVM tee's open handle; the path is passed absolute because the runtime's cwd is <install>/runtime, not mxcli's. The attach is best-effort — a logging failure warns to stdout rather than failing an otherwise-healthy start. Tests: TestStart_AttachesLogSubscriber (params), TestStart_NoLogSubscriberWhenUnset, TestStart_LogSubscriberFailureNonFatal. Docs: run-local skill, docs-site, and the fix-issue symptom table (findings #25, round 2). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JXnEgoc2NQP1Y2TWMCMXC4
ako
pushed a commit
that referenced
this pull request
Jul 29, 2026
Two entity-correctness fixes from the ledger project, both verified end-to-end on Mendix 11.12.1. #41 (CE6771 check gap): `create association from/to <ViewEntity>` passed `mxcli check --references` and exec, but `mx check` rejects it — associations to/from view entities are impossible. The reference checker now resolves both endpoints and rejects when either `isViewEntity` (new helper), naming it and pointing at a non-persistent alternative. Both directions caught. #39 (mx check crash): a `create or modify entity` dropping an indexed attribute left the index orphaned (its column referenced a removed GUID), and `mx check` CRASHED loading the project with an unhandled AggregateException. Two parts: - executor `reconcileDroppedIndexes`: when the statement lists no indexes, carry existing ones forward, pruning columns for dropped attributes (attr IDs survive by name) and dropping empty indexes — fixes partial drops (index(A,B)→index(A)). - backend `UpdateEntity`: an untouched empty Indexes PartList is "clean", so the codec passes the raw orphan through; force it dirty (add+remove) so the codec re-emits an empty list, clearing the raw — fixes the all-removed case. Verified: `mx check` → 0 errors (previously crashed). Tests: TestIsViewEntity, TestReconcileDroppedIndexes. Examples + symptom table. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JXnEgoc2NQP1Y2TWMCMXC4
ako
pushed a commit
that referenced
this pull request
Jul 29, 2026
… ledger cases Wave 1 (MDL-WF01/02/03, MDL-BUTTON01 — cases 1/2/4/5) is shipped. Record the ~10 ledger-driven checks added on the same pattern (MDL045-049, MDL-WIDGET13/14/15, MDL031 pass-through, view-entity association CE6771) plus the two write-path parity fixes (#24 navlist names, #39 orphaned index), and note the two originally- cataloged gaps that remain: case 3 (CE7412) and the standalone case-6 warn. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JXnEgoc2NQP1Y2TWMCMXC4
ako
pushed a commit
that referenced
this pull request
Jul 29, 2026
A `break` nested inside an if/case within a loop serializes a dangling
sequence-flow reference — `mx check` then CRASHES loading the project with an
unhandled System.AggregateException ("key … not present in the dictionary"), an
unrecoverable failure (same severity class as #39). A break placed directly in
the loop body serializes fine; only the useful `if <cond> then break` form is
affected.
The underlying flow-graph serialization bug is still open (a write-path fix).
MDL051 is the interim guard: on a LoopStmt, flag a break nested in an
if/case/inheritance-split (not descending into nested loops, which trap their own
break). Since the pattern currently CRASHES, a check-time rejection is a strict
improvement. Fix for the user: a guard variable (declare $Done Boolean = false; …
set $Done = true) — verified clean on mx check (11.12.1).
Test: TestValidateMicroflow_ConditionalBreak. Repro:
ledger-52-break-in-conditional.fail.mdl. Symptom table notes the real fix is the
write-path serialization; MDL051 is the interim.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JXnEgoc2NQP1Y2TWMCMXC4
ako
pushed a commit
that referenced
this pull request
Jul 29, 2026
….9 (FINDINGS #39) A workflow whose flow contains a "call microflow" activity was written with the on-disk $Type `Workflows$CallMicroflowTask`. Both checkers passed (mxcli check ✓, mx check → 0 errors), but on an 11.9+ project the runtime refused to load the ENTIRE model at boot: Failed to load model: ... Class 'Workflows$CallMicroflowTask' could not be found Mendix 11.9 (WOR-2802) split MicroflowBasedActivity into CallMicroflowActivity + AIAgentTaskActivity, renaming the on-disk $Type. Evidence from the cached toolchains: the 11.6.3 modeler knows only CallMicroflowTask; the 11.10 modeler carries both (the old one marked "Removed due to code refactoring ... WOR-2802") plus a conversion routine; the 11.10+ runtime metamodel jars know only CallMicroflowActivity. The 11.9 boundary matches the existing HasOwner→HasOwnerAttr domain-model gate. Fix: emit CallMicroflowActivity for projects >= 11.9 and keep CallMicroflowTask for older ones. The semantic model is unchanged — only the emitted $Type differs — so the tree is built with the legacy name and rewritten when targeting 11.9+. - modelsdk (default engine): applyCallMicroflowStorageName walks the built element tree; useCallMicroflowActivityName() gates on pv.IsAtLeast(11,9). Codec TypeDefaults + list-marker registered under both $Type names. Wired into CreateWorkflow/UpdateWorkflow and the ALTER-workflow activity serializer. - legacy engine: renameCallMicroflowTypeBSON rewrites the serialized BSON, gated the same way in serializeWorkflow and SerializeWorkflowActivity. - read path already folds both gen types into the one semantic CallMicroflowTask. Tests: rename walk (both directions) + encode-validity under the new name; version gate against the vendored 11.6.6 fixture; legacy BSON-rewrite unit test. Repro mdl-examples/bug-tests/263-workflow-callmicroflow-storage-name.mdl; symptom row added to fix-issue.md. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JXnEgoc2NQP1Y2TWMCMXC4
ako
pushed a commit
that referenced
this pull request
Jul 29, 2026
…ize context var (FINDINGS #39 regression) The 11.9 storage-name fix (CallMicroflowTask→CallMicroflowActivity) let the runtime load the model again, but the retest found the new class also structures outcomes and the parameter-mapping expression differently — so a call-microflow with a parameter or a non-void return now failed `mx check` with two errors that the tolerant old class had passed: - CE6686 "outcomes do not match the configured microflow": autoBindCallMicroflow injected a single VoidConditionOutcome regardless of return type. The 11.9+ class requires outcomes that match the microflow — a Boolean return needs true/false BooleanConditionOutcomes. defaultCallMicroflowOutcomes now generates them from the target microflow's ReturnType (Boolean → two branches, else → single default). - CE0117 "Error(s) in expression": the context parameter is named "WorkflowContext" and 11.9+ expressions are case-sensitive, so a user-written `$workflowContext` (the form in every example) is an undefined variable. normalizeWorkflowContextExpr rewrites it to `$WorkflowContext`. Verified against real mxbuild on BOTH classes: - Mendix 11.12.1 (CallMicroflowActivity): `call microflow ACT with (Ctx='$workflowContext')` on a Boolean-returning microflow → 0 errors (was 2). - Mendix 11.6.3 (CallMicroflowTask): same script → 0 errors (no regression). Unit tests for both helpers; bug-test 263 updated to the param+Boolean-outcome case. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JXnEgoc2NQP1Y2TWMCMXC4
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Round 2 of findings #25. PR #38 tee'd the runtime JVM's stdout/stderr to
.mxcli/runtime.log, but a re-test on the Sudoku app showed the file stays nearly empty: microflowLOGoutput and server-side exception stack traces never appear, so a page-action error still can't be diagnosed (the browser only shows the generic Mendix dialog).Root cause: a standalone runtime launched via
runtimelauncher.jarattaches no log subscriber by default — unlike a Studio Pro / m2ee run, which callscreate_log_subscriberafter start. Mendix application logs flow to log subscribers, not stdout, so with none attached they go nowhere.Fix
After a successful
start(and on every restart'sStart, since each fresh JVM has no subscriber), attach afilelog subscriber via thecreate_log_subscriberadmin action, mirroring m2ee-tools' post-start_configure_logging:max_rotate: 0is load-bearing — the JVM stdout tee (PR run --local: tee the Mendix runtime log to a file for debugging #38) holds an open fd on the same file, and a rotate-rename would detach it. Both writers append.<install>/runtime, not mxcli's).--runtime-log -disables the subscriber too.Tests
TestStart_AttachesLogSubscriber— asserts the params (type/filename/autosubscribe/name/max_rotate:0) after a successful start.TestStart_NoLogSubscriberWhenUnset— no subscriber whenLogSubscriberFileis empty.TestStart_LogSubscriberFailureNonFatal— a failingcreate_log_subscriberdoes not failStart; it warns instead.All docker unit tests pass; the only failure is the pre-existing environmental
TestServeIntegration(test app 11.6.3 vs MxBuild cache 11.12.1), unrelated to this change.Docs
runhelp text,run-localskill, and docs-site "Debugging a server-side error" now explain that two sources feedruntime.log(JVM tee + file log subscriber) and why.fix-issue.mdsymptom table extended with the round-2 entry.🤖 Generated with Claude Code
Generated by Claude Code