{"record":{"id":"87414ef33f1f8db0","repo":"mgth/LittleBigMouse","slug":"y-n","errorCode":null,"errorMessage":"${Y}!!  $*${N}","messagePattern":"(.+?)!!  \\$\\*(.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"run-lbm.sh","lineNumber":70,"sourceCode":"# Release -> target/release, Debug -> target/debug (matches the UI's config, which\n# is what LittleBigMouseClientService.FindHookPath prefers).\nif [[ \"$CONFIG\" == \"Release\" ]]; then RUST_PROFILE_DIR=\"release\"; else RUST_PROFILE_DIR=\"debug\"; fi\nRUST_BIN=\"$RUST_DIR/target/$RUST_PROFILE_DIR/lbm-hook\"\nSTAGED_HOOK=\"$BIN_DIR/lbm-hook\"\nLOG=\"${TMPDIR:-/tmp}/lbm-ui.log\"\n\n# Dev version stamp: v5.4.1 + 12 commits -> 5.4.1.12, so the About window tells\n# dev builds apart from releases. Empty (Directory.Build.props version applies)\n# when git or the tags are unavailable.\nVERSION=\"$(git -C \"$ROOT\" describe --tags --long --match 'v*' 2>/dev/null \\\n    | sed -E 's/^v//; s/-([0-9]+)-g[0-9a-f]+$/.\\1/')\"\n\n# Colours (skipped when not a TTY).\nif [[ -t 1 ]]; then C='\\033[36m'; D='\\033[90m'; Y='\\033[33m'; G='\\033[32m'; R='\\033[31m'; N='\\033[0m'\nelse C=''; D=''; Y=''; G=''; R=''; N=''; fi\nstep() { echo -e \"\\n${C}==> $*${N}\"; }\nnote() { echo -e \"    ${D}$*${N}\"; }\nwarn() { echo -e \"${Y}!!  $*${N}\"; }\n\n# 1. stop running instance(s). The bracketed letter keeps pkill from matching its\n#    own command line. Three patterns: `dotnet …dll` launches, apphost launches\n#    (the script prefers the apphost), and a distribution package launched through\n#    its /usr/bin/littlebigmouse entry point — whose command line carries none of\n#    the assembly name, so the first two patterns walk straight past it. Miss any\n#    of them and the old instance survives, the relaunch dies on the\n#    single-instance lock, and you are left looking at the stale app with an empty\n#    log. EVIOCGRAB releases on process exit, so this also frees any grabbed mice.\n#\n#    ORDER AND WAITING BOTH MATTER, and for the same reason: the UI relaunches the\n#    daemon whenever it loses the connection. That contract is only suspended for a\n#    clean tray Exit (`_quitting`, see \"Stop relaunching the daemon the UI is\n#    quitting\"); a signal does not go through QuitAsync, so a SIGTERM'd UI keeps its\n#    reconnect loop running while it winds down. Kill the daemon while any UI is\n#    still breathing and it spawns a REPLACEMENT, which survives into the launch\n#    below still holding the mice — and with a different PID, so it reads as a kill\n#    that failed rather than a spawn that should not have happened.","sourceCodeStart":52,"sourceCodeEnd":88,"githubUrl":"https://github.com/mgth/LittleBigMouse/blob/7a42f01d47d99d223b8ee33ba4019af82adf1c48/run-lbm.sh#L52-L88","documentation":"This is not a thrown exception: the string \"${Y}!!  $*${N}\" is the body of the warn() helper defined in run-lbm.sh. It prints a yellow '!!' warning line when the terminal is a TTY (colors are pre-expanded into the Y/N variables), and plain text otherwise. Any operational warning from the setup script — e.g. failure to stop a running instance — is emitted through it.","triggerScenarios":"Executing run-lbm.sh on any code path that calls warn \"...\"; the message only appears as a log line. The color codes interpolate when stdout is a TTY, and the arguments to warn fill $*.","commonSituations":"pkill failing to match a running instance (already stopped or unexpected process name); leftover socket/lock files found; non-fatal environment checks failing during setup.","solutions":["Read the text following '!!' in the script output — warn() is informational; the script usually continues unless a later step exits.","If the warning is about stopping instances, run pgrep -af 'littlebigmouse|dotnet' to find survivors and kill them manually.","Re-run the script in a TTY to see colorized output and full context of which step warned.","Inspect the call sites of warn in run-lbm.sh for the specific step that triggered the line and address its underlying condition."],"exampleFix":"# diagnostic\npgrep -af 'littlebigmouse|dotnet.*LittleBigMouse' || echo \"no instance running\"\n# manual stop if warn() reported a survivor\npkill -f 'LittleBigMouse.*\\.dll'; pkill -x littlebigmouse","handlingStrategy":"try-catch","validationCode":"# before running the script, ensure no stale instances block it\npgrep -af 'littlebigmouse|dotnet.*LittleBigMouse' && pkill -f 'LittleBigMouse.*\\.dll' || true","typeGuard":null,"tryCatchPattern":"out=$(./run-lbm.sh 2>&1) || { echo \"$out\" | grep '!!'; exit 1; }\necho \"$out\" | grep '!!' || true  # warnings are informational; only exit status matters","preventionTips":["Run the script in a TTY so warnings are colorized and easy to spot.","Treat warn() lines as informational; gate success on the script's exit code instead.","Stop running instances manually (pkill -f LittleBigMouse) before rerunning after a failed setup."],"tags":["shell","bash","setup-script","logging"],"backgroundTag":null,"analyzedSha":"7a42f01d47d99d223b8ee33ba4019af82adf1c48","analyzedAt":"2026-09-16T00:35:00.514Z","contentChangedAt":"2026-09-16T00:35:00.514Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}