Skip to content

[Bug]: Windows: portfolio real-tool scenario fails — node:sqlite cannot open the 267-char authority path (MAX_PATH); a second host-dependent layer behind it #8313

Open

Description

@AronSwan

Preflight

  • I searched existing issues and discussions for this behavior.
  • This report is not an unpatched security vulnerability.
  • The report and attachments contain no credentials or private/internal material.

Issue origin

Observed or reproduced in a real environment.

LoopX version or commit

main @ faab5f5c291c — also reproduces at 225698b313

Host or runtime surface

Other: Windows 10.0.26300 x64; Python 3.14.8, Node v26.8.1, LongPathsEnabled=1

LoopX area

Control plane (goals, todos, quota, scheduler, registry, runtime)

Problem

test_portfolio_real_tool_scenarios_choose_from_latest_quota_result fails deterministically on this Windows host (10 runs across the two commits, no pass; run logs retained) and passes on another host at 225698b313 (#7433). Two layers, separated by a control run:

Layer 1 — the reported failure, causally isolated. With the default pytest tmp root, the failing oracle fixture's SQLite authority path is 267 chars — with its -wal sidecar past the 260-char MAX_PATH — and node:sqlite fails to open database files at such path lengths here even with LongPathsEnabled=1 (probe: 250-char path opens, 258–267 all fail with unable to open database file; Node v26.8.1, script in diagnostics; same class as #7888 — the same failure mode is reported for node's DatabaseSync in openclaw#113304 and for bun:sqlite in bun#33336). SqliteAuthorityStore.open(true) fails before the file exists (the oracle runtime has no sqlite file afterwards), and readFailure (sqlite_authority_store.ts:152) collapses the real error into the generic "lock contention" message. Control: re-running with a short --basetemp (path ~200 chars) lets the store create successfully and this payload disappears — confirming path length as the cause of this layer.

Layer 2 — a further host-dependent failure behind it. With the short tmp root, the import succeeds but the test still fails at the portfolio assertion (qualification_passed=False; scenarios report actor_result_invalid, portfolio_aborted_after_actor_error on several turn_* scenarios). So at least one more Windows/environment-dependent problem exists in the real-tool actor path; we have not isolated it yet.

(Update 2026-11-08: layer 2 is now isolated — see the follow-up comment below; it reads as a by-design platform prerequisite: the real-tool arm requires sandbox-exec/bubblewrap, which Windows hosts don't have. Layer 1 stands unchanged.)

Asks: surface the underlying SQLite error in the status; make authority paths work under deep runtime roots on Windows (#7888 class); any pointer on what actor_result_invalid usually indicates in this portfolio would help us dig into layer 2. Filed as the separate report promised on #7403.

Minimal reproduction

python -m pytest -q "tests/control_plane/test_actual_default_model_behavior_portfolio.py::test_portfolio_real_tool_scenarios_choose_from_latest_quota_result"

Node-side minimal repro of the open failure: in diagnostics below.

Expected behavior

The test passes as on the other host; at minimum, a store failure surfaces the actual SQLite error.

Actual behavior

import_fixture_authority raises with the payload below (default tmp root); the failing oracle runtime has no sqlite file afterwards. With a short tmp root the store gets created and the failure moves to the portfolio assertion (layer 2).

Sanitized diagnostics

Exact cold_import payload (verbatim from a failing run):

{"ok":false,"schema_version":"loopx_coordination_shadow_admin_v0","action":"prepare-import","goal_id":"portfolio-goal","executed":false,"cold_import":{"schema_version":"loopx_cold_source_import_result_v0","ok":false,"status":"failed","executed":false,"authority_changed":false,"execution_authority_granted":false,"reason_code":"cold_import_unavailable","reason":"{\"status\":\"unavailable\",\"reason_code\":\"provider_read_unavailable\",\"reason\":\"SQLite authority store could not be read; check database availability and lock contention\"}","legacy_writer_fenced":null,"legacy_fallback_used":false},"decision_read_from_shadow":false}

Node-side minimal repro (this host, LongPathsEnabled=1):

import { DatabaseSync } from "node:sqlite";
// build a dir so join(dir, "authority-x.sqlite") has the target length, then:
const db = new DatabaseSync(file);        // write-mode open
db.exec("PRAGMA journal_mode=WAL");

Results: LEN=250 OPEN_OK; LEN=258/259/260/261/262/267 OPEN_FAIL ERR_SQLITE_ERROR: unable to open database file. Directory creation (mkdirSync recursive) succeeds at those lengths — only the SQLite open fails.

Control run (layer separation): python -m pytest -q <same test> --basetemp=C:/lp/bt — the oracle store is created (authority-*.sqlite + -wal/-shm present), the provider_read_unavailable payload is gone, and the run fails instead at the final assertion: ('turn_required_vision_replan', ['actor_result_invalid'], []), ('turn_scoped_gate_successor_replan', ['portfolio_aborted_after_actor_error'], None) (expanded from a truncated log line), ('turn_quota_hot_path_human_gate_invariance', ['portfolio_aborted_after_actor_error'], None) (log retained).

Elimination notes: PRAGMA busy_timeout = 5000 is set in SqliteAuthorityStore.open; a concurrent holder with an idle connection or open BEGIN IMMEDIATE does not block readers (WAL); the product never sets locking_mode=EXCLUSIVE. npm dev dependencies are not installed here; the runtime path runs TS directly via node --experimental-strip-types, so they appear unrelated (flagged as a difference). The 9 failing runs include a second git worktree at the same commit.

Activity

  1. added
    bugSomething isn't working
    triageNeeds maintainer triage or routing.
    on Nov 7, 2026
  2. AronSwan commented on Nov 7, 2026

    @AronSwan
    CollaboratorAuthor

    Follow-up (TL;DR): layer 2 is isolated — it closes the open question from the report, and reads as a by-design platform prerequisite rather than a bug on this path.

    Directly invoking the failing actor outside pytest (_real_tool_actors(...)["replan_semantic_action_actor"](run_id)) surfaces the raw error that the portfolio collapses into actor_result_invalid:

    RuntimeError: Native qualification needs sandbox-exec (macOS) or bubblewrap (Linux); unrestricted execution is not a fallback
    

    loopx/control_plane/testing/vision_shell_host.py:36-45 — shell_isolation_available() checks darwin + sandbox-exec or bwrap; there is no Windows branch, and this host has neither tool.

    Control runs (short --basetemp, so layer 1 is bypassed; all three arms fail with the same failure set — untruncated via separate --assert=plain runs: 1 actor_result_invalid + 7 portfolio_aborted_after_actor_error of 22 scenarios, first 14 passing, no other codes — ruling out dev deps and console encoding):

    • no dev deps → fail
    • after npm ci --ignore-scripts → fail (same set)
    • with PYTHONUTF8=1 → fail (same set)

    Two observations for maintainers:

    1. The first failure runs through the real-tool qualification arm, which requires a platform sandbox by design; the other seven scenarios abort after that actor error. The portfolio test has no platform skipif (the only "skip" in the file is an assertion on skip_count), so on Windows the fail-closed RuntimeError surfaces as actor_result_invalid three levels down — a reader cannot tell "unsupported platform" from "actor misbehaved". Would a suite-level skip/unsupported marker (or carrying the RuntimeError message into the failure receipt) be considered?
    2. Layer 1 (node:sqlite failing to open authority stores on long paths — 258+ chars in our probe) stands independently, and it is the one currently hidden behind the generic SQLite message.

    Probe transcript and arm logs retained; happy to attach anything useful.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingtriageNeeds maintainer triage or routing.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions