Troubleshooting
Start with kinhin heal: the healing agent fixes many of the problems below on its own, lists the fixes waiting for your approval, and says what only you can do.
kinhin doctorshows "tart: NOT FOUND" — runkinhin setup repair tart(or use the setup window's fix button), then re-runkinhin doctor.- "tart: INSTALLED BUT KILLED ON LAUNCH ✗" — the OpenAI-tap bottle is un-notarized; Gatekeeper kills it before it runs.
kinhin doctorand the setup app print/offer the exact rollback commands; the manual equivalents are in Installing Tart. - Jobs queue but no VMs start — check that the job's
runs-on:contains every label in your config; the scaler only counts jobs it could actually run. - Scale set:
runner group 'default' was not found; create it in GitHub before attaching— withscale_set:on a GitHub account, kinhin looks the runner group up by an exact, case-sensitive name, and its default (default) is not GitHub's built-in group name (Default), so no scale set is ever created and the listener retries forever. Setrunner_group: "Default"underscale_set:inconfig.yaml, spelled exactly as GitHub spells it, then restart the app — account-level config is not live-reloaded. Walkthrough: Troubleshooting scale sets. - VM boots but the runner never registers — the base image may predate the injected agent. Re-run
kinhin image prepare. Full logs:kinhin logs -n 200or~/Library/Application Support/Kinhin/logs/kinhin.log. lifecycle failed: runner registration failed … ssh: connect to host <ip> port 22: Operation timed out— the fresh VM booted and got an IP, but its SSH server did not answer within the bring-up window (at leastvm_boot_timeout, default 300s). Common causes: the first boot of a freshly prepared image (macOS first-boot work can delay sshd for minutes — big images like full Xcode are the usual offenders), the host being busy with a bake or other jobs, or a softnet hiccup. kinhin retries the TCP/SSH probes for the whole window, then deletes the VM and scales a fresh one — the job normally lands on the replacement, so an isolated occurrence is harmless. If it repeats: raisevm_boot_timeout(e.g.600) for slow images, keep the host quiet during boot storms, and re-prepare the image if the guest agent is flaky on every boot.- Tart:
Error Domain=VZErrorDomain Code=-9 "The virtual machine encountered a security error."(withFailed to create new HostKey;tart ipthen saysno IP address found, is your VM running?) — the macOS login keychain's password often differs from your account password. Check it withsecurity unlock-keychain ~/Library/Keychains/login.keychain-db: if that says The user name or passphrase you entered is not correct., reset the keychain. In a reported case, over Screen Sharing, Keychain Access → Settings → Reset My Default Keychain fixed it. This deletes the passwords saved in the login keychain, so re-enter the ones you need, then confirm the kinhin token withkinhin doctor --check-tokens. Do not delete the keychain instead; that removes the same passwords without fixing the mismatch. Full steps: Tart FAQ, Keychain password mismatch. Other errors such asSecKeyCreateRandomKey_ios failedcan share this cause. Steps that did not help in the reported cases: reinstalling Tart, rebooting, stopping Multipass, updating the Command Line Tools. - Token rejected — re-run
kinhin auth set; the PAT needsreposcope and access to the repo. - First launch blocked — only applies to old releases or locally built copies (official releases are signed and notarized). Right-click → Open, or
xattr -cr /Applications/kinhin.app.
Building kinhin and CI failures (for contributors)
CI builds on the kinhin-xcode runner with Xcode 26.5 (Swift 6.3.x). A newer Xcode on your Mac can accept code that CI's compiler rejects or crashes on, so a green local build is not proof. Run the CI jobs on your branch and read the log from the terminal:
bash
gh workflow run ci.yml --ref my-branch # test, tsan and docs on your branch
gh run list --workflow ci.yml --branch my-branch --limit 3 # find the run
gh run view <run id> --json jobs --jq '.jobs[] | "\(.name) \(.conclusion) \(.databaseId)"'
gh api repos/RabinApps/kinhin/actions/jobs/<job id>/logs --allow-escape-sequences | sed 's/\x1b\[[0-9;]*m//g' > job.logerror: passing closure as a 'sending' parameter risks causing data raceswith the noteclosure captures reference to mutable let 'x'(SendingClosureRisksDataRace) — a locallet x = Mutex(...)is captured by aTaskoraddTaskclosure that the enclosing task also uses. Swift 6.3 rejects a noncopyableMutexthere; newer compilers accept it. UseLocked(...)(Sources/KinhinKit/Core/Locked.swift) instead: samewithLock, but aSendableclass. After a crash or an error the compiler only reports the files it reached, so convert every localMutexin the file (and its siblings), not only the line it names.compile command failed due to signal 6,SmallVector unable to grow, andWhile emitting IR SIL function "@$s…_TR"— the compiler crashed building a reabstraction thunk. The one we hit came from handing a main-actor method to an API as a function value (Binding(get: …, set: select)). Pass a closure instead (set: { select($0) }).swift demangle '<the symbol>'names the types in the thunk, which points at the code to look for. Bisect on CI with a throwawayci-bisect/*branch whose workflow builds one product, since the failing compiler is not on your Mac.- Localization tests fail only on CI (
the compiled String Catalog is missing from …kinhin_kinhin-app.bundle, or text like1 instanceswhere1 instanceis expected) — Swift 6.3's default (native) build system copiesLocalizable.xcstringswithout compiling it, so no plural forms exist. Build and test with--build-system swiftbuild(Swift 6.4 already defaults to it). Every kinhin script and workflow passes it; add it when you runswift testby hand with a 6.3 toolchain. A release packaged without it would ship an uncompiled catalog. - A test passes alone and locally but fails in
swift test --parallelon CI, for example because it finds files another test left behind — parallel runs use several processes that share the machine's temp directory. Give each test its own directory and never assert on, or clean, the shared temp directory.UpdateChecker(downloadRoot:)and the update tests show the pattern. docsjob:Video suite … Cannot find package 'yaml'— that job runs the video unit tests with Node only. The video scripts loadyamllazily (only when a YAML config is read) andscripts/video-check.shruns a one-timenpm ci --omit=devwhennode_modulesis missing. Do not add top-level imports of packages to scripts that the CI planner or the claims check import.- Orphaned
kinhin daemonprocesses after the e2e suite — each belongs to a/tmp/ke2e-*sandbox that is gone. A sandbox now stops its daemons when it is disposed, andscripts/e2e-sweep.sh --forceclears the rest. Checkps eww -p <pid> | tr ' ' '\n' | grep KINHIN_SUPPORT_DIRshows a/tmp/ke2e-…directory before you kill one by hand. - Reproducing CI's compiler locally — the swift.org 6.3.2 toolchain can be unpacked without installing it (
pkgutil --expand-full), but it needs an SDK from the same generation: this Mac's macOS 27 SDK needs Swift 6.4, so the build fails withunknown argument: '-target-arch-variant'. Without Xcode 26.5's SDK, use CI as the oracle.
