Skip to content

Write generated/generator.json only after message generation completes - #1595

Merged
minggangw merged 1 commit into
RobotWebTools:developfrom
KR-Ravindra:fix/write-generator-marker-last
Sep 9, 2026
Merged

Write generated/generator.json only after message generation completes#1595
minggangw merged 1 commit into
RobotWebTools:developfrom
KR-Ravindra:fix/write-generator-marker-last

Conversation

@KR-Ravindra

Copy link
Copy Markdown
Contributor

Problem

If message generation does not run to completion, rclnodejs.init() keeps treating the partial generated/ tree as complete. Every interface that was never written then fails with MESSAGE_NOT_FOUND on every start, and the only way out is to delete generated/ by hand. The two realistic ways to get there are the generating process being killed part-way (SIGKILL/OOM during npm install, Ctrl-C on generate-ros-messages, CI/container teardown) and any single package failing to generate (EACCES, ENOSPC, a malformed interface). In the second case npm install also exits 0, because the postinstall script only logs the error, so the partial tree is left behind silently.

Root cause

  • rosidl_gen/index.cjs:87-90 copies generator.json (the version marker init() uses to decide whether regeneration is needed) into generated/ before the per-prefix generateInPath() loop at rosidl_gen/index.cjs:103-105 has generated a single interface file.
  • index.js:422-424 (getCurrentGeneratorVersion() / forced) only regenerates when that file is absent or carries an older version, so a partial tree with a current-version marker is never regenerated.
  • scripts/generate_messages.cjs:36-38 catches the error, prints Caught error: ... and returns normally, so the process exits 0.

Fix

  • rosidl_gen/index.cjs: write generated/generator.json last, after the generateInPath() loop. generated/ is now created with fse.mkdirs() up front (the generator.json copy used to create it implicitly). A tree left behind by an interrupted or failed run has no marker, getCurrentGeneratorVersion() returns null, and init() regenerates it on the next start with no other change.
  • scripts/generate_messages.cjs: process.exit(1) in the catch handler so npm install and npx generate-ros-messages report the failure instead of succeeding with a partial tree.
  • test/test-messsage-generation-overlay.js: regression test that points AMENT_PREFIX_PATH at a prefix whose ament index lists a .msg file that does not exist, runs generateAll(true), and asserts that it fails and that no generated/generator.json was written.

How tested

New test against the unmodified generator:

  override interface in overlay tests
    1) failed generation leaves no generator.json marker
  0 passing (100ms)
  1 failing
  1) override interface in overlay tests
       failed generation leaves no generator.json marker:
      AssertionError [ERR_ASSERTION]: Expected no generator.json after a failed generation
      + expected - actual
      -false
      +true

With the fix:

  override interface in overlay tests
    ✔ failed generation leaves no generator.json marker (148ms)
  1 passing (156ms)

Also checked that a successful generateAll(false) followed by generateAll(true) still produces generated/generator.json, generated/package.json and generated/srv_msg/, and that node scripts/generate_messages.cjs now exits 1 when a package fails to generate (generated/ is left without generator.json). npx prettier --check and npx eslint pass on the changed files.

Links

This change was prepared with an AI agent operated by KR-Ravindra, who reviewed and tested it.

generateAll() copied the version marker into generated/ before the
generateInPath() loop, so a run that was killed part-way or failed on
one package left a tree that init() treated as complete and every
missing interface raised MESSAGE_NOT_FOUND until generated/ was
deleted by hand. Write the marker last so a partial tree has no
generator.json and init() regenerates it on the next start. Make
scripts/generate_messages.cjs exit non-zero on error so npm install
does not report success for a partial tree. Add a regression test.

Fix: RobotWebTools#1594
@coveralls

Copy link
Copy Markdown

Coverage Status

coverage: 90.812% (+0.007%) from 90.805% — KR-Ravindra:fix/write-generator-marker-last into RobotWebTools:develop

@KR-Ravindra KR-Ravindra left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Round 1 self-review.

Checked against develop: rosidl_gen/index.cjs copies generator.json into generated/ before the generateInPath() loop, init() only regenerates when that marker is missing or older than the generator, and scripts/generate_messages.cjs logs the error and returns normally, so the description matches the code.

  1. Marker is now written after the loop and generated/ is created with fse.mkdirs() up front (the copy used to create it implicitly), so an interrupted or failed run leaves no marker and the next init() regenerates. Looks correct.
  2. process.exit(1) in the postinstall catch makes npm install report the failure instead of exiting 0 with a partial tree.
  3. The new mocha case uses the file's existing generateMessages() / GENERATED_PATH helpers, restores AMENT_PREFIX_PATH and removes the temp prefix in finally.

CI: full ROS 2 matrix (humble, jazzy, kilted, lyrical, rolling; arm64 + x64; pixi builds) green, coverage unchanged. Marking ready.

@KR-Ravindra
KR-Ravindra marked this pull request as ready for review September 8, 2026 22:20
Copilot AI lite review requested due to automatic review settings September 8, 2026 22:20

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

The change directly addresses the reported partial-generation failure mode and adds a targeted regression test, with only a minor logging improvement suggested.

Pull request overview

This PR hardens ROS message generation so a partially generated generated/ tree is no longer treated as complete by rclnodejs.init(), and generation failures correctly surface as non-zero exits (preventing silent broken installs).

Changes:

  • Delay writing generated/generator.json until after all interfaces finish generating, so interrupted/failed runs leave no “complete” marker.
  • Make scripts/generate_messages.cjs exit with status 1 on generation errors (so npm install/npx generate-ros-messages fail loudly).
  • Add a regression test ensuring failed generation does not leave generated/generator.json behind.
File summaries
File Description
rosidl_gen/index.cjs Moves the version marker write to the end of successful generation and ensures generated/ exists before writing other outputs.
scripts/generate_messages.cjs Ensures message generation failures propagate as a non-zero process exit.
test/test-messsage-generation-overlay.js Adds a regression test for the “no marker after failed generation” behavior.
Review details
  • Files reviewed: 3/3 changed files
  • Comments generated: 1
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines 36 to 39
} catch (e) {
console.log(`Caught error: ${e}`);
process.exit(1);
}
@minggangw

Copy link
Copy Markdown
Member

lgtm, merging

@minggangw
minggangw merged commit de87656 into RobotWebTools:develop Sep 9, 2026
17 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.

4 participants