Files
remmina-mac/docs/ERRORS.md
T

16 KiB

Error log (ERRORS.md)

Every error hit while building/releasing RemminaMac — cause, fix, status. Updated with every build.

As of 2026-09-22 · version 0.7.0 · macOS arm64 · Swift 5.9+ · Xcode 15+

Overview

# Date Phase Error Severity Status
1 2026-09-21 swift build (debug) WindowGroup<some View> has no member 'windowTitle' blocking ✅ fixed
2 2026-09-21 swift build -c release no errors, just slow first link (~40 s) info ✅ ok
3 2026-09-21 release script dist/ missing from .gitignore → binary almost committed medium ✅ fixed (ignored)
4 2026-09-21 Gitea upload GET /api/v1/user → 401 with old credentials blocking ✅ fixed — new credentials, push + v0.1.0 live
5 2026-09-21 app bundle + DMG no errors: signing ok, UDZO DMG, mount verified info ✅ ok
6 2026-09-21 SSH connect no terminal opened: NSAppleScript failed silently (no AppleEvents permission/handling) blocking ✅ fixed — in-app PTY terminal (Dracula) + .command fallback
7 2026-09-21 ANSI parser (test) feed() flushed chunk AFTER parseCSI → wrong style medium ✅ fixed — flush before style switch
8 2026-09-21 SSH session dies instantly, no message stderr shared the PTY: macOS drops unread master data on slave close → bare "code 255" blocking ✅ fixed — stderr→pipe, TCP pre-check, error banner
9 2026-09-21 swift build Result<Void, String>: String is not Error (follow-on DispatchQueue errors) blocking ✅ fixed — completion as (String?) -> Void
10 2026-09-21 icon generator (RenderIcon.swift) 3 Swift errors: non-optional guard let, Int * CGFloat, wrong preview path small ✅ fixed
11 2026-09-21 password feature request: store passwords + keys AND use them (stored but never used) feature ✅ done — sshpass auto-login, else interactive
12 2026-09-21 "always connection wrong" user report without details open ⬜ partly: editor validation + copyable error report
13 2026-09-21 Permission denied with correct password text substitution in input field mangled special chars high ✅ fixed — hardened input field (all substitutions off, 9/9)
14 2026-09-21 Terminal works, app doesn't (same password) SSH agent socket missing for GUI processes → maybe key login in Terminal high ✅ app forwards agent socket; user confirmation open
15 2026-09-21 crash on type + send cause unclear (not reproducible headless) critical ⬜ hardened (v0.5.3); crash log requested
16 2026-09-22 profile edits had no effect session cache ignored host/password/key corrections high ✅ fixed — fingerprint reconfig (9/9)
17 2026-09-22 rzsv: pre-check timeout port 22 dropped server-side (443 ok) — not an app bug external ⬜ server side: fail2ban/VPN/firewall
18 2026-09-22 host-key yes/no impossible ssh without controlling terminal: /dev/tty ENXIO → silent abort critical ✅ ctty-run helper (double-fork) + fingerprint popup
19 2026-09-22 empty popup (see screenshot) if let in sheet takes empty branch with no update path medium ✅ .sheet(item:) + background keyscan
20 2026-09-22 terminal not fully interactive single-line input, no completion, no vim feature ✅ done — SwiftTerm emulator (0.7.0)
21 2026-09-22 yes-asked-twice + password ignored popup-accept race; sshpass installs went stale medium ✅ verified no re-ask; sshpass in fingerprint

Template for new errors

## #N — Title
**Phase:** ...
**Log:** ...
**Cause:** ...
**Fix:** ...
**Verified:** ...
**Status:** ⬜ open / ✅ fixed

How errors get here

  • Every swift build / swift build -c release / script run with an error → log excerpt + exit code goes here.
  • Gitea push/release errors likewise.
  • New tests: AnsiParser via swiftc harness, PTYSession smoke tests, Keychain roundtrips, TCP checks, host-key flow vs local paramiko server, SwiftTerm core headless.

#1 — windowTitle doesn't exist on WindowGroup

Phase: first swift build Log:

RemminaMacApp.swift:14:10: error: value of type 'WindowGroup<some View>' has no member 'windowTitle'

Cause: windowTitle(_:) is not a WindowGroup modifier; the title goes in the WindowGroup init. Fix: WindowGroup("RemminaMac") { ... }. Status: ✅ fixed.

#2 — Slow but clean release build

Phase: bash scripts/build-release.sh 0.1.0 → swift build -c release (~40 s first link). Cause: none — release optimization + link just take a while cold; faster on rebuilds (.build/ cache). Status: ✅ ok.

#3 — dist/ almost committed

Cause: dist/ held ZIP + unpacked binary, .gitignore didn't know it. Fix: ignore .build/, dist/, *.zip, *.sha256. Status: ✅ fixed.

#4 — Gitea upload: 401 despite reachable server

Phase: POST /api/v1/user/repos + GET /api/v1/user on https://git.sysdaemon.xyz (v1.27.3 confirmed via /api/v1/version). Log: GET /user -> 401 {"message":"invalid username, password or token"} — tried logins x3 and x3@sysdaemon.xyz, both 401 (Basic auth via Python, no shell-quoting issue). Fix: with corrected credentials: GET /api/v1/user → 200 (login x3), repo x3/remmina-mac created (201), push ok, release v0.1.0 + assets uploaded. Status: ✅ fixed.

#6 — SSH click opens no terminal (user bug report)

Cause: SSHService.openInTerminal used NSAppleScript(tell application "Terminal" …) — fails silently without NSAppleEventsUsageDescription and with no error handling. Fix: Services/PTYSession.swift (real PTY via posix_openpt), Views/EmbeddedTerminalView.swift (in-app Dracula terminal, auto-connect), external fallback via .command file + NSWorkspace (no automation rights needed). Verified: build ok; parser 8/8; PTY smoke (/bin/echo → output + exit 0); ssh -G through PTY ok. Status: ✅ fixed.

#7 — ANSI parser: text got the wrong style

Phase: swiftc harness during #6. Log: text("rot", fg: nil) instead of fg: 1. Cause: chunk flushed only after the SGR switch. Fix: flush() before parseCSI. Harness 8/8 green. Status: ✅ fixed.

#8 — Terminal connects then dies instantly, no message (user bug report)

Repro (harness, exact app path ssh -p 1 nobody@127.0.0.1): exit 255, output shows only the session note — ssh's error lost. Ground truth (Python pty): even /bin/echo hello yields b'' when read only AFTER child exit; reading promptly yields b'hello-py\r\n' → macOS drops unread PTY master data on slave close (then EIO). Our DispatchSourceRead loses that race for instant-exit children — and ssh writes everything (incl. "Connection refused") to stderr, which shared the PTY. Fix: stderr → Pipe (buffered data survives child exit), stdin/stdout stay on PTY; non-blocking finalFlush + epoch-guarded lifecycle; TCP pre-check (Network.framework, 4 s) with plain-language messages; red error banner + Diagnose/Retry buttons. Verified: refused harness now shows the error (PASS); cat roundtrip, ssh -G, TCP harness (closed/open/empty) PASS. Status: ✅ fixed.

#9 — Build: Result<Void, String> invalid

Log: error: type 'String' does not conform to protocol 'Error' (+ follow-on errors). Fix: TCPCheck.check uses (String?) -> Void (nil = ok, else message). Status: ✅ fixed.

#10 — Icon generator build errors

Log: non-optional guard let (?? already unwraps); Int * CGFloat; preview landed in .iconset/ instead of /tmp/. Fix: assign ?? fallback directly; CGFloat(...); path corrected. Status: ✅ fixed. Icon: Resources/AppIcon.icns (reproducible via scripts/generate-icon.sh), preview docs/icon-preview.png.

#11 — Store AND use passwords (user request)

State: passwords/passphrases were stored in Keychain but never used for login (ssh always asked interactively). Done: SSHService.loginSecret() (profile password → key passphrase), pure/testable sessionConfig(): with secret + sshpass → sshpass -e ssh/sftp … + SSHPASS env (never command line/logs); otherwise direct call + interactive prompt. PTYSession.customEnv + auto-login flag; status shows auto-login state. Editor: saved indicator (✓), delete button, sshpass hint. Verified: config harness 9/9 (incl. "password never on command line"); real Keychain roundtrip 7/7. Note: without sshpass (brew install sshpass) the interactive prompt remains. Status: ✅ done.

#12 — "Always connection wrong" (user report, details open)

State: reported without target host, banner text or credentials — not reproducible remotely. Checklist: user@host in host field or ssh:// prefix → live editor warnings now; whitespace trimmed; wrong password / missing key → banner + Diagnose; server blocks (fail2ban, key-only) → check server logs. Done: Models/ProfileValidation.swift (7/7), password right below username, "Copy report" in banner (no secrets). Status: ⬜ waiting for error report.

#13 — Permission denied with correct password (user error report)

Report: administrator@sysdaemon.xyz:22, ssh asks 3x → Permission denied (publickey,password). Same password works in Terminal.app. Cause: the terminal input was a stock TextField — macOS silently substitutes characters (" → “”, -- → —, autocorrect). A password with special chars arrives mangled; Terminal shows nothing wrong, ssh just denies. Verified: stock NSTextField has these switches on, and can't even disable dash substitution (compiler proof). Fix (Views/TerminalInputField.swift, later superseded by SwiftTerm): NSTextView-based field with all substitutions explicitly off; Secure variant via NSSecureTextField; Enter → send, paste normalization. Verified: harness 9/9 (all flags off). Status: ✅ fixed — retest with v0.5.1+.

#14 — Terminal.app logs in, RemminaMac doesn't (same password)

User answers: v0.5.1 installed, password login, Terminal.app works with the same data. Analysis: app side fully verified → difference must be environmental. Main suspect: SSH agent — Finder-launched GUI processes don't inherit SSH_AUTH_SOCK. If Terminal silently uses an agent key (not the password), the app fails with the password. Verified: launchctl getenv SSH_AUTH_SOCK returns the socket. Fix: SSHService.agentSocket() → TerminalManager injects SSH_AUTH_SOCK into the ssh env (coexists with SSHPASS). Verified: harness 4/4. User confirmation check: ssh-add -l + ssh -o IdentitiesOnly=yes administrator@sysdaemon.xyz. Status: ✅ app side done — waiting for confirmation.

#15 — Crash on type + send (user report)

State: "crashes as soon as I type and send." Not reproducible headless — every layer green alone. Ruled out by test: SIGPIPE on write (macOS returns EIO, no signal; send-after-stop survives); view layer (real coordinator + NSTextView: umlauts/quotes/paste/Enter, 200 programmatic sets); PTY roundtrip, refused, Keychain, TCP harnesses. Hardened (v0.5.3, unproven as THE crash): detach delegate during programmatic sets (no state mutation mid-render); safe pointer in send(). Still needed if it recurs: Console.app → Crash Reports → newest RemminaMac entry → Exception Type, Termination Reason, crashed thread. Status: ⬜ waiting for feedback / crash log.

#16 — Profile edits had no effect ("still doesn't work")

State: user kept reporting failure after fixes. Code review (TerminalManager.session): a once-created session was reused forever — host/password/key corrections never reached it. Fix: config fingerprint (proto/host/port/user/extraArgs/key path/secret value) per session; on mismatch with a non-running session: stop + reconfigure (same object, tabs stay). Running sessions are never reconfigured underfoot (disconnect first). Verified: harness 9/9. Status: ✅ fixed — retest with v0.5.4 (re-save profile once).

#17 — rzsv: pre-check timeout (not an app bug, screenshot proof)

Picture: tab rzsv (administrator@sysdaemon.xyz:22), banner "pre-check: no answer in 4 s", ssh correctly NOT started. Measured (same machine): sysdaemon.xyz → 185.117.250.190; port 443 ok in 0.02 s, port 22 dropped (timeout, no refused). Server reachable, SSH port dropped from this network. No client can connect from here — the pre-check was right. Likely causes: fail2ban ban after the many denied attempts (fail2ban-client status sshd → unban); VPN on/off mismatch; firewall allows 22 only from certain networks. Update from user: port 22 is blocked on the company network; hotspot works. Confirmed. Status: ⬜ server/network side.

#18 — Host-key yes/no impossible (user screenshot: Terminal works, app only says "Host key verification failed.")

Analysis: Terminal shows the Are you sure...? prompt (with fingerprint), app aborts without prompt. Proof via -v: read_passphrase: can't open /dev/tty: Device not configured — ssh prompts need a controlling terminal; our PTY slave wasn't one (GUI app has none, child inherits none). Affects password AND yes/no prompts. Fix: Sources/ctty-run/ctty-run.c (C helper, SPM target): double-fork (needed because Apple's Process starts children in their own process group → direct setsid = EPERM) → setsid → slave open (= ctty) → exec ssh. stderr stays on the parent pipe (loss-free). stop() kills the process group (no orphans, verified). Plus Views/HostKeySheet.swift flow: ssh-keyscan fingerprint upfront → popup (SHA256/MD5, type) → accept (→ shared ~/.ssh/known_hosts) / decline; red MITM warning + ssh-keygen -R path on changed keys. Verified (local paramiko server): bug reproduced (no prompt, exit 255) → after fix: ctty proven via ps (ttys001), yes/no visible + answerable, password accepted, shell active. HostKeyService: unknown/accept/known/changed/revoke/unreachable green. Status: ✅ fixed (v0.6.0).

#19 — Fingerprint popup appears empty (user screenshot)

Picture: sheet window present but tiny and contentless; status stuck on "checking …". Cause: .sheet(isPresented:) + if let info content: if evaluation takes the empty branch at presentation time, the empty branch has no dependency on the state var → the sheet never updates, stays empty. Classic SwiftUI trap. Fix: .sheet(item: $hostKeyRequest) with HostKeyRequest: Identifiable — content structurally always exists. Plus HostKeyService.status (blocking keyscan) moved to a background queue — the UI used to freeze during "checking …". Status: ✅ fixed (v0.6.1).

#20 — Terminal not fully interactive (user request)

State: single-line input row, no Tab completion, no vim/full-screen apps. Done (0.7.0): SwiftTerm emulator (v1.20.0 SPM dep) as Views/SwiftTermView.swift: cursor addressing, colors, scrollback, selection, direct keyboard (completion, arrows, Ctrl+C, Esc), vim/htop. Dracula palette via installColors + native fg/bg. PTY layer feeds raw bytes (onData); keystrokes go straight to the pty master (sendBytes); resizes propagate via TIOCSWINSZ (setWinsize). Old input row + TerminalInputField.swift removed (SwiftTerm handles keys natively, immune to macOS substitutions). Verified: headless emulator core 6/6 (text, absolute cursor addressing, alt-screen on/off, clear, 16-color palette); app-path login + shell still green. Status: ✅ done.

#21 — Asked for yes twice + password ignored (user reports)

Analysis: (a) empty-popup era (#19) forced ssh's own yes/no prompt — fixed by the popup fix; verified no re-ask after popup accept (harness asserts no "Are you sure" post-accept). (b) sshpass installs went stale: the session fingerprint didn't include sshpass presence, so installing sshpass later never switched to auto-login. Fixed by including it in TerminalManager.configTag (now nonisolated pure function). Verified: no-ask + login green; tag changes on sshpass variance. Status: ✅ fixed.