Before submitting
Area
apps/server (CLI in the t3 package plus the orchestration decider)
Problem or use case
On a headless server deployment I wanted to remove a project that still had threads. t3 project remove <project> fails with an invariant error:
ProjectLiveServerDeclaredResponseError: Server request failed (internal_error, ...)
cause: OrchestrationCommandInvariantError
commandType: project.delete
detail: Project '<project-id>' is not empty and cannot be deleted without force=true.
There is no way to pass force from the CLI, and the web UI does not expose it either. So on a server-only setup there is no supported path to remove such a project. This also bites in the archived-threads case from #2866, where the project looks empty in the UI but deletion still fails.
Proposed solution
Add a flag to the existing command:
t3 project remove --force <project>
The server already supports this: ProjectDeleteCommand has an optional force boolean, and the decider cascades thread.delete for all active threads before emitting project.deleted when force: true is set. The CLI's projectRemoveMutation just never sets the field.
Without --force, keep the current behavior, but ideally surface the invariant message directly instead of a generic internal_error (the actual reason is only visible in the server trace log).
Why this matters
Headless/server deployments manage projects exclusively through the CLI. Right now they dead-end on a state the server can already resolve. A CLI flag would also give affected users a clean workaround for #2866 until the UI mismatch is fixed.
Smallest useful scope
Just the --force flag on t3 project remove, setting force: true on the dispatched project.delete command. No UI changes, no new error surfacing.
Alternatives considered
I verified the server-side behavior on 0.0.28 by temporarily patching the dispatched command in dist/bin.mjs to include force: true. t3 project remove <id> then worked exactly as expected: both remaining threads and the project were marked deleted in one command. That is obviously not a sustainable workaround since it does not survive package updates.
Risks or tradeoffs
--force deletes threads irreversibly, so the flag should be explicit and never the default. Possibly worth printing the number of threads that will be deleted before proceeding.
Examples or references
Before submitting
Area
apps/server (CLI in the
t3package plus the orchestration decider)Problem or use case
On a headless server deployment I wanted to remove a project that still had threads.
t3 project remove <project>fails with an invariant error:There is no way to pass
forcefrom the CLI, and the web UI does not expose it either. So on a server-only setup there is no supported path to remove such a project. This also bites in the archived-threads case from #2866, where the project looks empty in the UI but deletion still fails.Proposed solution
Add a flag to the existing command:
The server already supports this:
ProjectDeleteCommandhas an optionalforceboolean, and the decider cascadesthread.deletefor all active threads before emittingproject.deletedwhenforce: trueis set. The CLI'sprojectRemoveMutationjust never sets the field.Without
--force, keep the current behavior, but ideally surface the invariant message directly instead of a genericinternal_error(the actual reason is only visible in the server trace log).Why this matters
Headless/server deployments manage projects exclusively through the CLI. Right now they dead-end on a state the server can already resolve. A CLI flag would also give affected users a clean workaround for #2866 until the UI mismatch is fixed.
Smallest useful scope
Just the
--forceflag ont3 project remove, settingforce: trueon the dispatchedproject.deletecommand. No UI changes, no new error surfacing.Alternatives considered
I verified the server-side behavior on
0.0.28by temporarily patching the dispatched command indist/bin.mjsto includeforce: true.t3 project remove <id>then worked exactly as expected: both remaining threads and the project were marked deleted in one command. That is obviously not a sustainable workaround since it does not survive package updates.Risks or tradeoffs
--forcedeletes threads irreversibly, so the flag should be explicit and never the default. Possibly worth printing the number of threads that will be deleted before proceeding.Examples or references