You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
[Desktop][Headless] Packaged headless start needs an external connector key, blames the port/data folder when it is missing, and writes data next to the exe #2181
Observed (v0.2.0 rehearsal artifact, run 33228952652, 927236bd0)
Running the packaged Windows build headless for an isolated acceptance journey (TASKDECK_HEADLESS=1, ASPNETCORE_URLS=http://127.0.0.1:5218, isolated LOCALAPPDATA, no Llm__* in the environment) surfaced three related behaviours. None broke the journey once understood, and none affects the normal double-click (non-headless) path — but the diagnostics are actively misleading and the data-location rule is undocumented.
Headless Production refuses to auto-generate the connector key, and the fatal message blames the wrong thing.FirstRunBootstrapper.ShouldAutoGenerateConnectorKey(isProduction, isHeadless) => !isProduction || !isHeadless (backend/src/Taskdeck.Api/FirstRun/FirstRunBootstrapper.cs:684-685) is deliberate, so ValidateProductionSecrets throws when no Connectors__EncryptionKey is supplied. The user-visible result is TASKDECK_DESKTOP_FATAL code=startup_failed with "Taskdeck could not start. Check that the configured port is available and the data folder is writable." Neither the port nor writability was the cause. Packaged builds ClearProviders() with no console logger, so the real exception is never printed anywhere. (Precedent: fix: diagnose retired provider configuration in desktop startup #2016 made the retired-provider case diagnosable; this is the same class.)
Headless Production stores data next to the executable, not under %LOCALAPPDATA%\Taskdeck.ResolveLocalConfigPath (FirstRunBootstrapper.cs:57-74): only a non-headless Production desktop uses durable per-user storage; headless keeps the executable-local compatibility path. The run wrote appsettings.local.json, taskdeck.db, -wal, -shm, and taskdeck.db.migrate.lock into the extracted release tree — the folder the quick start tells users not to keep data in. TASKDECK_HEADLESS is documented nowhere in docs/releases/WINDOWS_QUICK_START.md, docs/platform/CONFIGURATION_REFERENCE.md, or README.md.
Restart hazard that follows from 1. With a supplied key the run persisted only {"Jwt":{"SecretKey":…}}; restarting the same data folder without re-supplying the identical Connectors__EncryptionKey hits the guard "An existing database was found … but no supplied or persisted connector encryption key is recoverable … Refusing to generate replacement connector or JWT secrets" and refuses to start. (Code-path reading; not live-reproduced.)
Acceptance
When ValidateProductionSecrets fails in a packaged headless run, the desktop fatal line names the actual cause (missing Connectors__EncryptionKey) and the remedy, instead of the port/writability boilerplate — same shape as fix: diagnose retired provider configuration in desktop startup #2016.
TASKDECK_HEADLESS and its data-location consequence are documented in docs/platform/CONFIGURATION_REFERENCE.md (one row) with a pointer from the quick start's "Where your data lives" section.
Decide and record whether headless Production should honour an explicit app-data root (e.g. an env override) so automation runs can stay out of the release tree; if not, say so in the same doc row.
Regression test for the fatal-message path (FirstRunBootstrapper unit level is enough).
Not tag-blocking for v0.2.0: normal users never set TASKDECK_HEADLESS. Found by the 2026-08-29 rehearsal journey; full evidence in the v0.2.0 release deck.
Observed (v0.2.0 rehearsal artifact, run 33228952652,
927236bd0)Running the packaged Windows build headless for an isolated acceptance journey (
TASKDECK_HEADLESS=1,ASPNETCORE_URLS=http://127.0.0.1:5218, isolatedLOCALAPPDATA, noLlm__*in the environment) surfaced three related behaviours. None broke the journey once understood, and none affects the normal double-click (non-headless) path — but the diagnostics are actively misleading and the data-location rule is undocumented.FirstRunBootstrapper.ShouldAutoGenerateConnectorKey(isProduction, isHeadless) => !isProduction || !isHeadless(backend/src/Taskdeck.Api/FirstRun/FirstRunBootstrapper.cs:684-685) is deliberate, soValidateProductionSecretsthrows when noConnectors__EncryptionKeyis supplied. The user-visible result isTASKDECK_DESKTOP_FATAL code=startup_failedwith "Taskdeck could not start. Check that the configured port is available and the data folder is writable." Neither the port nor writability was the cause. Packaged buildsClearProviders()with no console logger, so the real exception is never printed anywhere. (Precedent: fix: diagnose retired provider configuration in desktop startup #2016 made the retired-provider case diagnosable; this is the same class.)%LOCALAPPDATA%\Taskdeck.ResolveLocalConfigPath(FirstRunBootstrapper.cs:57-74): only a non-headless Production desktop uses durable per-user storage; headless keeps the executable-local compatibility path. The run wroteappsettings.local.json,taskdeck.db,-wal,-shm, andtaskdeck.db.migrate.lockinto the extracted release tree — the folder the quick start tells users not to keep data in.TASKDECK_HEADLESSis documented nowhere indocs/releases/WINDOWS_QUICK_START.md,docs/platform/CONFIGURATION_REFERENCE.md, orREADME.md.{"Jwt":{"SecretKey":…}}; restarting the same data folder without re-supplying the identicalConnectors__EncryptionKeyhits the guard "An existing database was found … but no supplied or persisted connector encryption key is recoverable … Refusing to generate replacement connector or JWT secrets" and refuses to start. (Code-path reading; not live-reproduced.)Acceptance
ValidateProductionSecretsfails in a packaged headless run, the desktop fatal line names the actual cause (missingConnectors__EncryptionKey) and the remedy, instead of the port/writability boilerplate — same shape as fix: diagnose retired provider configuration in desktop startup #2016.TASKDECK_HEADLESSand its data-location consequence are documented indocs/platform/CONFIGURATION_REFERENCE.md(one row) with a pointer from the quick start's "Where your data lives" section.FirstRunBootstrapperunit level is enough).Not tag-blocking for v0.2.0: normal users never set
TASKDECK_HEADLESS. Found by the 2026-08-29 rehearsal journey; full evidence in the v0.2.0 release deck.