Skip to content

fix: stale pre-0.75 runtime cache entries no longer break startup for SDK embedders - #1196

Merged
michaelneale merged 3 commits into
mainfrom
fix/startup-lenient-runtime-cache-scan
Aug 8, 2026
Merged

fix: stale pre-0.75 runtime cache entries no longer break startup for SDK embedders#1196
michaelneale merged 3 commits into
mainfrom
fix/startup-lenient-runtime-cache-scan

Conversation

@michaelneale

@michaelneale michaelneale commented Aug 8, 2026

Copy link
Copy Markdown
Collaborator

Summary

Upgrading to 0.75.x with an existing native runtime cache no longer aborts startup for SDK embedders. A cache entry written by a pre-0.75 loader (manifest without per-file checksums) is now skipped with a warning during startup runtime resolution, instead of failing the whole cache scan before the download/install fallback can run.

This is the startup-path completion of #1170 (issue #1162). #1170 fixed the resolver's cache enumeration, but the startup fast-path in mesh-llm-host-runtime still used the strict full-cache NativeRuntimeCache::installed(), where one stale manifest ?-aborts everything.

Who hits this

Anyone embedding the host runtime via the SDK (initialize_host_runtime()) on a machine with a pre-0.75 runtime cache — observed during the Buzz desktop upgrade to v0.75.0:

native runtime artifact meshllm-native-runtime-darwin-aarch64-metal does not declare file checksums

The installed CLI was unaffected by accident of packaging: install.sh ships a native-runtimes/ directory beside the binary, so startup takes the bundle-discovery branch (which reads manifests leniently) and never reaches the strict cache scan. SDK embedders have no adjacent bundle dir, fall into resolve_installed_native_runtime_plancache.installed(), and failed hard — before allow_download could rescue them.

What changed

  • New NativeRuntimeCache::installed_lenient() enumerates the whole cache and collects unreadable entries (missing/malformed/checksum-failing manifests) as skipped instead of failing the scan.
  • Startup runtime resolution (resolve_installed_native_runtime_plan) uses the lenient scan and emits a tracing::warn! per skipped entry with path and reason.
  • The runtime-control backend options view uses it too, so one stale entry no longer hides all installed backend kinds from the console.
  • Strict verification is unchanged where it matters: installs, downloads, and the load plan for the selected runtime still enforce per-file checksums. Only enumeration of neighbors is lenient.

Validation

  • New test stale_pre_checksum_cache_entry_does_not_block_startup_plan (host runtime): a valid current-version runtime plus a pre-checksum 0.74.0 cache entry resolves to the valid runtime.
  • New test installed_lenient_skips_legacy_manifest_and_keeps_valid_runtime (native-runtime crate): lenient scan returns the valid runtime, reports the stale one as skipped, and asserts the strict scan still errors on the same cache (documenting why startup must not use it).
  • cargo test -p mesh-llm-host-runtime --lib — 1924 passed.
  • cargo test -p mesh-llm-native-runtime --lib — 27 passed.
  • cargo fmt --all --check, cargo clippy -p mesh-llm-native-runtime --all-targets -- -D warnings — clean. (-p mesh-llm-host-runtime clippy has 28 pre-existing unfulfilled-lint-expectation errors on main, unchanged by this PR.)
  • Empirical repro on macOS arm64: a binary with no adjacent bundle dir and an isolated cache containing only a stale pre-checksum 0.74.0 entry — v0.75.0 fails startup with the checksum error; this branch warns, skips, and proceeds to normal runtime resolution.

Protocol

No wire or protocol impact. Cache-directory compatibility only: pre-0.75 cache entries are now skipped (and pruned by existing maintenance) rather than fatal. No manifest format change.

Summary by CodeRabbit

  • Bug Fixes
    • Improved runtime discovery so valid runtimes continue loading even when unusable or legacy cache entries are present.
    • Added clearer logging when invalid runtime entries are skipped.
    • Prevented legacy pre-checksum cache entries from blocking startup or runtime state detection.

@coderabbitai

coderabbitai Bot commented Aug 8, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: fdd558dc-e7a4-4a61-ab52-8897d7d97402

📥 Commits

Reviewing files that changed from the base of the PR and between 4397ba9 and 4f80cad.

📒 Files selected for processing (1)
  • crates/mesh-llm-native-runtime/src/cache.rs
🚧 Files skipped from review as they are similar to previous changes (1)
  • crates/mesh-llm-native-runtime/src/cache.rs

📝 Walkthrough

Walkthrough

Native runtime cache discovery now preserves valid runtimes when other entries have invalid manifests or checksums. Startup logs skipped entries, and the runtime state route uses the lenient scan.

Changes

Native runtime cache handling

Layer / File(s) Summary
Lenient cache scan
crates/mesh-llm-native-runtime/src/cache.rs, crates/mesh-llm-native-runtime/src/lib.rs
The cache exposes LenientInstalledScan and SkippedNativeRuntime. installed_lenient returns valid runtimes, records invalid entries, and preserves sorting. Tests cover invalid cache entries and directories without manifests while strict scanning still fails.
Startup cache resolution
crates/mesh-llm-host-runtime/src/system/native_runtime.rs
Startup uses lenient scanning, logs skipped entries, and selects valid runtimes. A regression test covers a legacy entry alongside a valid runtime.
Runtime state integration
crates/mesh-llm-host-runtime/src/api/routes/runtime_control_state_sources.rs
The runtime control state route uses installed_lenient() when collecting backend kinds.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Startup
  participant NativeRuntimeCache
  participant Logger
  participant RuntimeControlStateRoute
  Startup->>NativeRuntimeCache: installed_lenient()
  NativeRuntimeCache-->>Startup: valid runtimes and skipped entries
  Startup->>Logger: log skipped entries
  RuntimeControlStateRoute->>NativeRuntimeCache: installed_lenient()
  NativeRuntimeCache-->>RuntimeControlStateRoute: valid runtimes
Loading

Possibly related PRs

Suggested labels: experimental

Suggested reviewers: ndizazzo

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: stale pre-0.75 runtime cache entries no longer block startup for SDK embedders.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/startup-lenient-runtime-cache-scan

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@crates/mesh-llm-native-runtime/src/cache.rs`:
- Around line 162-163: Update the runtime-directory scanning logic around the
manifest check to record a SkippedNativeRuntime containing the directory and an
explicit reason when the manifest is missing, not a regular file, or cannot be
read, instead of silently continuing. Use metadata/read errors to distinguish
inaccessible manifests from missing ones, and add a regression test covering a
runtime directory without manifest.json.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 82da9166-a9bb-4c9a-9b7b-cda29754f900

📥 Commits

Reviewing files that changed from the base of the PR and between 126109b and 5868579.

📒 Files selected for processing (4)
  • crates/mesh-llm-host-runtime/src/api/routes/runtime_control_state_sources.rs
  • crates/mesh-llm-host-runtime/src/system/native_runtime.rs
  • crates/mesh-llm-native-runtime/src/cache.rs
  • crates/mesh-llm-native-runtime/src/lib.rs

Comment thread crates/mesh-llm-native-runtime/src/cache.rs Outdated
A native runtime cache entry written by a pre-0.75 loader (no per-file
checksums, issue #1162) aborted the embedded startup path before the
download/install fallback could run. The installed CLI was unaffected
because it discovers its binary-adjacent bundle dir first and never
reaches the strict full-cache scan; SDK embedders (no bundle dir) hit
the strict scan and failed hard.

Add NativeRuntimeCache::installed_lenient(), which enumerates the whole
cache and collects unreadable entries as skipped instead of failing the
scan. Startup runtime resolution now uses it and warns per skipped
entry; the runtime-control backend options view uses it too so one
stale entry no longer hides all installed backends.
@michaelneale
michaelneale force-pushed the fix/startup-lenient-runtime-cache-scan branch from 5868579 to bc4fb94 Compare August 8, 2026 06:54
Address review feedback: a runtime directory whose manifest.json is
missing, not a regular file, or unreadable is now recorded as a skipped
entry with an explicit reason instead of being silently ignored, so the
startup warning surfaces every unusable cache entry. Adds a regression
test for a runtime directory without manifest.json.

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@crates/mesh-llm-native-runtime/src/cache.rs`:
- Around line 149-159: Update the directory traversal in installed_lenient to
skip and record cache-version directories whose read_dir fails, then continue
scanning other versions. Apply the same lenient handling to per-entry
enumeration and file_type() failures when the entry path is available,
preserving valid runtime discovery and fallback resolution.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 05c66293-a892-4b23-bb38-d7bf32d4d703

📥 Commits

Reviewing files that changed from the base of the PR and between 5868579 and 4397ba9.

📒 Files selected for processing (1)
  • crates/mesh-llm-native-runtime/src/cache.rs

Comment thread crates/mesh-llm-native-runtime/src/cache.rs

@i386 i386 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Reviewed and fixed the remaining cache-scan robustness issue. The lenient startup scan now skips unreadable cache-version directories, runtime-entry metadata failures, and iterator item failures where no path is available, while continuing to discover valid runtimes. The preceding PR commit already handles missing/non-regular manifests as skipped entries. Validated with cargo fmt --all -- --check, cargo check -p mesh-llm-native-runtime, cargo clippy -p mesh-llm-native-runtime --all-targets -- -D warnings, and cargo test -p mesh-llm-native-runtime --lib (28 passed). mesh-llm-host-runtime check is green; its broad Clippy run is currently blocked by pre-existing unrelated unfulfilled_lint_expectations warnings. Approving.

@micspiral

Copy link
Copy Markdown

Desk-checked this from Buzz (SDK embedder) — it fixes the startup abort for us.

Setup: pinned Buzz's mesh-llm deps to this branch's head (4f80cad) and left a
pre-checksum cache in place, i.e. the failing upgrade shape:

~/Library/Caches/mesh-llm/native-runtimes/
  0.73.1      runtime.files = 0     <- written by a pre-0.75 loader
  0.74.0      runtime.files = 0
  0.74.0-rc8  runtime.files = 0
  0.75.0      runtime.files = 24    <- valid, correct version, present

Before (pinned to the v0.75.0 tag), initialize_host_runtime() aborted:

host runtime init: native runtime artifact meshllm-native-runtime-darwin-aarch64-metal
does not declare file checksums

Buzz has no executable-adjacent bundle dir (the desktop app doesn't ship one), so it
falls through to resolve_installed_native_runtime_plancache.installed(), and a
single stale entry took out the whole scan even though the valid 0.75.0 entry was
sitting right there. That's also why the installed CLI is unaffected: its bundle dir
means the cache enumeration is never reached.

After this branch: no abort, runtime resolved, and our end-to-end
share-compute → agent → inference example passed 4/4 with the stale entries still in
place.

One extra step needed to test from a hash, worth noting for anyone else doing this:
the branch's CARGO_PKG_VERSION is 0.72.1, so default_release_manifest_url pointed
at the v0.72.1 release, which ships Skippy ABI 0.1.27 while the build wants 0.1.35:

no compatible MeshLLM native runtime is installed or installable
for MeshLLM 0.72.1 / Skippy ABI 0.1.35

Setting MESH_LLM_BUILD_VERSION=0.72.1+g4f80cad takes the is_sha_build path in
default_manifest_url, which resolves from releases/latest and picks up the ABI
0.1.35 artifact. Not a defect in this PR — just a consequence of pinning an
unreleased rev.

What I did not verify: the new Skipping unusable native runtime cache entry
warnings. Our example installs no tracing subscriber, so warn-level lines aren't
printed. I only observed the absence of the fatal error plus a successful start, not
the skip logging itself.

@michaelneale
michaelneale enabled auto-merge (squash) August 8, 2026 07:37
@michaelneale
michaelneale merged commit f2ba0b5 into main Aug 8, 2026
45 checks passed
@michaelneale
michaelneale deleted the fix/startup-lenient-runtime-cache-scan branch August 8, 2026 07:46
michaelneale added a commit to block/buzz that referenced this pull request Aug 10, 2026
v0.75.1 carries the upstream fix (Mesh-LLM/mesh-llm#1196): startup now scans
the native-runtime cache leniently (`installed_lenient`), skipping unusable
entries instead of aborting the whole scan on the first one.

That removes the blocker this branch has carried since the v0.75.0 bump. On a
machine with a pre-0.75 cache, v0.75.0 failed with:

  native runtime artifact meshllm-native-runtime-darwin-aarch64-metal
  does not declare file checksums

because caches written by older loaders have no per-file checksums, and the
strict enumeration covered every version under the cache root.

Verified on a machine that still has the offending entries in place
(0.73.1, 0.74.0, 0.74.0-rc8 all with `runtime.files = 0`), with no bundle
directory and no MESH_LLM_BUILD_VERSION override:

- no checksum abort
- the v0.75.1 runtime installed itself alongside the stale entries
- crates/buzz-relay/examples/mesh_agent_e2e passed 4/4 (explicit-model chat,
  auto-model chat, oversized-budget rejection, agentic tool use)

Pins move in both manifests (six mesh-llm crates in the desktop Tauri crate,
two in buzz-relay) with both lockfiles refreshed. The v0.75.1 release
publishes native-runtimes.json with 13 artifacts including
darwin-aarch64-metal at Skippy ABI 0.1.35, which matches what the crates
compile against.

Signed-off-by: Michael Neale <michael.neale@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants