š” Medium project/handlers.ts:72
A failed launch.launch leaves the thread-scoped attachment copies orphaned, so repeated failed launches accumulate files while the pending originals remain retryable. The handler maps the launch error without releasing claimed.claimedPaths; release those paths on launch failure before returning the error.
| 1 | - .pipe(Effect.mapError(unavailable)); |
| 2 | + .pipe( |
| 3 | + Effect.tapError(() => Claims.releaseClaimedAttachments(claimed.claimedPaths)), |
| 4 | + Effect.mapError(unavailable), |
| 5 | + ); |
š Reply "fix it for me" or copy this AI Prompt for your agent:
| 1 | In file @apps/server/src/mcp/toolkits/project/handlers.ts around line 72: |
| 2 | |
| 3 | A failed `launch.launch` leaves the thread-scoped attachment copies orphaned, so repeated failed launches accumulate files while the pending originals remain retryable. The handler maps the launch error without releasing `claimed.claimedPaths`; release those paths on launch failure before returning the error. |
The proposed blanket cleanup is unsafe at this boundary. In the unchanged ThreadLaunchService, message.dispatch commits the attachment references at lines 520-534, then getThreadProjection at lines 548-550 can still fail; the later preparation re-read can also fail. A launch error therefore does not prove those copies are unused. Releasing claimedPaths in tapError can delete bytes referenced by an accepted durable message. This wrapper deliberately retains copies on an uncertain outcome, as stated in the PR limits. Cleanup that distinguishes proven pre-acceptance failure from partial acceptance belongs in the shared launch service as a separate change; no unconditional release is being added here.