Skip to content

[Bug]: [Windows] Computer Use broken since 3.1.4 — CuaUtility exits before ready; failure misreported as 'Device restricted (parental controls)' #548

Open

Description

@syxscott

Product or interface

Desktop app

Version

3.1.4.127 (Electron 42.8.0), Windows x64

Platform

Windows

OS version and architecture

Windows 10 x64 (build 26200)

Issue area

Tool call / permission / sandbox

Steps to reproduce

  1. On Windows 10 x64, MiniMax Code Desktop 3.1.4.127 (hot-updated from the previous 3.1.x build on 2026-10-23 17:36), open the plugin marketplace and enable the official Computer Use plugin (computer-use v1.0.1).
  2. The authorization dialog appears. Both the "Screen Recording" and "Accessibility" rows show 「设备受限(家长控制)」 ("Device restricted (parental controls)"), and the dialog only offers a "Use" button — no "Open System Settings" action.
  3. The conversation provides no computer_* tools at all.
  4. Check %APPDATA%\MiniMax\logs\main-computer-use.log: every activation forks the CuaUtility helper, which exits with code 1 about 0.5 s later — computer_utility_exited_before_ready. This has happened on every attempt since the update (79 occurrences as of 2026-10-26); the last successful start was 2026-10-21 14:17 on the previous build (utility_ready, driverVersion=0.22.1, sdkSource=upstream-package).

Expected and actual behavior

Expected: on Windows, the plugin enables and the computer-use runtime starts; the authorization dialog either shows a Windows-appropriate state ("no permission required") or a real diagnostic when startup fails.

Actual:

  1. The dialog renders the macOS TCC model (Screen Recording / Accessibility) on Windows and labels the failure "Device restricted (parental controls)", sending users to check Screen Time / MDM / system permission toggles — none of which are involved.
  2. The CuaUtility helper never becomes ready, so Computer Use is completely unavailable.

Code-level root cause (verified by extracting and reading the shipped app.asar):

  • The utility entry (cua-entry.js) resolves its data directory as dataDir: process.env.MINIMAX_DATA_DIR ?? '' and swallows every startup error: .catch(() => process.exit(1)).
  • The main process forks it via utilityProcess.fork(...cua-entry.js, [], { env: { ...process.env, MAVIS_CUA_GENERATION, MAVIS_CUA_DIAGNOSTICS }, stdio: 'pipe' }) — the data directory is only inherited through the main process's transient process.env state (MINIMAX_DATA_DIR is a temporary override prepared for local-runtime forks and deleted by restoreLocalRuntimeDataDirOverride()), never injected explicitly for this child.
  • startCuaUtilityServer → prepareDesktopComputerUseComponent(dataDir) → prepareInstalledPackagedComponent validates as its first check: if (!path.isAbsolute(input.dataDir) || !path.isAbsolute(input.packagedRoot)) throw new ComputerUseError('computer_component_invalid', ...). A missing/empty MINIMAX_DATA_DIR therefore fails before anything else; the rejection is swallowed by .catch(() => process.exit(1)), and the main process only logs exitCode: 1.
  • The UI then maps any probe failure to the fallback: blocked() = { accessibility: 'restricted', screenRecording: 'restricted', captureReady: false }, rendered by i18n (cu_status_restricted) as 「设备受限 (家长控制)」. The win32 success branch of snapshot() would return { accessibility: 'not-required', screenRecording: 'not-required', captureReady: true } — so on Windows, restricted always means "probe failed", never "parental controls".

All other failure modes were verified clean, so the dataDir handoff is the only surviving candidate:

Candidate failure Verification result
Build-injected release token invalid Decoded the token shipped in the app resources; the win32-x64 digest matches the shipped component.json SHA-256 exactly (42dd5ca4…a74)
Packaged component missing resources\resources\computer-use\0.34.1\win32-x64\ is complete (component.json, driver, executables)
Component files corrupted All 10 files declared in component.json re-hashed: 10/10 match
Unsafe ownership / permissions verifyTreePermissions skips the uid/mode checks entirely on win32 (symlink-only walk); no symlinks present
Platform unsupported win32-x64 is inside the supported set

The packaged component is also healthy in isolation: minimax-computer-use.exe doctor --json reports "ok": true (UI Automation CoCreateInstance(CUIAutomation) succeeds, interactive desktop attached, EnumWindows returns visible windows), and the install directories ~/.minimax/computer-use/components/0.34.1/win32-x64 and ~/.minimax-computer-use do not exist — confirming prepareInstalledPackagedComponent has never completed.

Regression timeline: 2026-10-21 14:17 start succeeded on the previous build (npm upstream-package path, no packaged-component preparation involved); hot-update to 3.1.4 on 2026-10-23 17:36 switched to the "packaged component + signed release token" path; every activation since 2026-10-23 19:58 fails identically.

Redacted error summary

[2026-10-23 19:58:01.553] [info] [CuaUtility] forked generation=1 pid=unknown
[2026-10-23 19:58:02.145] [warn] [CuaUtility] child lifecycle ended generation=1 pid=24692 {"exitCode":1}
[2026-10-23 19:58:02.145] [warn] [CuaUtility] startup unavailable; continuing without Computer Use: computer_utility_exited_before_ready

Repeated on every activation. Note there are no utility_output lines at all before the exit — the failure happens before the first log-capable stage, consistent with the first-line path validation in prepareInstalledPackagedComponent.

Suggested fixes

  1. On Windows, don't render the macOS TCC items (Screen Recording / Accessibility). When the probe fails, surface the actual error code (e.g. computer_component_invalid / computer_utility_exited_before_ready) instead of 「设备受限(家长控制)」.
  2. Inject dataDir explicitly into the CuaUtility utilityProcess.fork() (or pass it through the cua-connect message) instead of depending on the main process's transient process.env.MINIMAX_DATA_DIR state.
  3. Log the real errorCode to main-computer-use.log when the utility fails to start — today only exitCode=1 is recorded, which is what made this regression so expensive to diagnose.

Before submitting

  • I have searched existing issues.
  • I have included my version and removed sensitive information.

Activity

  1. wittkung commented on Oct 31, 2026

    @wittkung

    Cross-linking the macOS instance of this failure family, since it is the same symptom with the same misreported label but a different error code.

    Three details that may help triage both:

    1. The error code differs per platform. Windows reports computer_component_invalid (empty/non-absolute dataDir); macOS reports computer_runtime_directory_unsafe, thrown by the shipped SDK's ancestor check in node_modules/@mavis/computer-use/dist/desktop-lock.js (mode & 0o022 === 0 is required for every existing ancestor of the runtime root, and the runtime root is hardcoded under $HOME).

    2. The honest label already exists but is unreachable. The renderer has settings.cu_status_unavailable = "Bridge unavailable" for exactly this case, but dist/main/modules/local-runtime/computer-use/component-permissions.js converts every exception into blocked() → restricted → "Restricted (parental controls)", so that branch is never reached when the runtime fails to start. On a machine without any device-management restriction, the label is simply wrong.

    3. A one-command workaround exists for the macOS case (not for the Windows one): the ancestor check passes as soon as the home directory is not group/world writable — chmod g-w,o-w ~ — after which the component installs and verifies, and the shipped driver works (Accessibility/Screen Recording granted, live capture verified). The ACL entry for a second local account is unaffected by the mode change.

    Not a duplicate of this issue: different platform, different error code, different packaging constraint.

  2. syxscott commented on Nov 1, 2026

    @syxscott
    Author

    Adding the Windows-side evidence for this report, obtained by calling the product's own shipped modules instead of inferring from the code path. This is the technique that pins the failure mode on Windows.

    Reproduction with the shipped library on this Windows host

    I extracted the shipped @mavis/computer-use modules from app.asar (dist/component.js, dist/packaged-component.js, dist/desktop-lock.js, dist/contracts.js) and called them directly, exactly as the utility does:

    // dataDir = C:\Users\Administrator\.minimax   (the profile root in use here)
    prepareInstalledPackagedComponent({
      dataDir, packagedRoot: '<app>\resources\resources\computer-use',
      releaseToken: '<build-injected token>', platform: 'win32', arch: 'x64',
    })
    Input Result
    dataDir: 'C:\Users\Administrator\.minimax' OK — release token verified, manifest digest matched, all 10 component files re-hashed and matched, component copied into …\computer-use\components\0.34.1\win32-x64\42dd5ca4… and re-verified after install
    dataDir: '' THREW computer_component_invalid: Component and profile roots must be absolute host-owned paths.
    dataDir: '.minimax' (relative) THREW the same computer_component_invalid
    privateDirectory(desktopLockRoot()) resolved — no throw

    Two things this settles:

    1. On Windows, an empty/non-absolute dataDir is the only preparation-time failure that remains. Every other candidate was executed successfully against the real files: the build-injected release token, the manifest digest, the per-file hashes, the tree verification, and the runtime-directory safety checks. verifyTreePermissions and assertSafeAncestors skip their uid/mode checks on win32 by design (process.platform !== 'win32' && …), so the macOS-style computer_runtime_directory_unsafe path does not apply here — privateDirectory() succeeds on this host.

    2. A ~/.minimax junction is not the cause. On this machine C:\Users\Administrator\.minimax is a junction to D:\AppData\.minimax; resolveProfileDataDir() resolves it via realpath and the preparation completes normally.

    So on Windows the failure requires dataDir to be empty or relative at the moment the helper starts — which is what dataDir: process.env.MINIMAX_DATA_DIR ?? '' yields when MINIMAX_DATA_DIR is unset in the main process at fork time (the variable is a transient override prepared for local-runtime forks and deleted again by restoreLocalRuntimeDataDirOverride(); utilityProcess.fork inherits process.env but does not inject the value explicitly).

    Cross-platform note on the shared UI defect

    The Windows and macOS reports (#572) have different underlying causes — macOS fails on computer_runtime_directory_unsafe (home directory 0777), Windows fails on computer_component_invalid (empty data dir) — but both render the identical dialog, because the utility's startup error is swallowed by .catch(() => process.exit(1)) and every probe failure collapses into blocked() → restricted → 「设备受限 (家长控制)」.

    That makes two of the suggested fixes platform-independent and worth doing for both platforms:

    • log the real errorCode before the utility exits (today only exitCode=1 is recorded — that missing code is the entire reason this took an exclusion analysis rather than a log read);
    • do not render the macOS TCC rows (Screen Recording / Accessibility) on Windows, and never label a generic probe failure as "parental controls".

    Verified locally with the shipped bundle: Desktop 3.1.4.127, Windows 10 x64 (build 26200), Node v24.22.1, profile root C:\Users\Administrator\.minimax.

  3. hetaoBackend commented on Nov 1, 2026

    @hetaoBackend
    Collaborator

    Sorry this sat for five days without a reply from us. That's on us, not on you.

    Thank you @syxscott for the original report and for reproducing it against the shipped @mavis/computer-use modules. Pinning it to computer_component_invalid from an empty or non-absolute dataDir, rather than a permissions problem, is exactly what we needed. Thanks also to @wittkung for linking the macOS side in #572.

    I'm bringing this to the desktop team today, and we'll treat #548 and #572 as one failure family. We'll post the owner and the fix plan here. We'll also stop showing 「设备受限(家长控制)」 when the helper fails to start, since that message sends people the wrong way.

  4. dyh-sjtu commented on Nov 1, 2026

    @dyh-sjtu
    Collaborator

    Thanks again @syxscott for the detailed evidence, and @wittkung for linking #572.

    Windows root cause: fixed in Desktop 3.1.8 and later. In 3.1.4 the profile root is checked by assertNoSymlink. Node reports an NTFS junction as a symbolic link, so a ~/.minimax junction (in your case C:\Users\Administrator\.minimax → D:\AppData\.minimax) is rejected with the same computer_component_invalid code as an empty dataDir. The message text tells the two apart: a junction gives "Symbolic links are not allowed in component/runtime paths.", while an empty or relative dataDir gives "Component and profile roots must be absolute host-owned paths."

    resolveProfileDataDir(), which realpaths the profile root before these checks, first shipped in 3.1.8. 3.1.4 does not have it, so a reproduction that calls it must have used modules from a later build. 3.1.8+ also writes the startup errorCode to the log before the helper exits, which was missing from the 3.1.4 logs.

    Misleading 「设备受限(家长控制)」 status: fix in review. A component failure will now show as "Unavailable" instead of "Restricted (parental controls)". The error code will be written to main-computer-use.log, and on Windows the dialog will no longer list the macOS Screen Recording and Accessibility rows. We'll update this issue once it ships.

    Could you update to 3.1.8 or later (3.1.10 is current) and try Computer Use again? If it still fails, please attach main-computer-use.log and the utility_exit line with its errorCode. That will show whether a second cause remains.

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

    desktopMiniMax Code desktop app

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions