Skip to content

fix: Imposter.delete() of an absent imposter succeeds over HTTP but throws embedded (rift#1371) - #318

Merged
EtaCassiopeia merged 1 commit into
masterfrom
fix/rift-308-idempotent-imposter-delete
Oct 16, 2026
Merged

EtaCassiopeia merged 1 commit into
masterfrom
fix/rift-308-idempotent-imposter-delete

Conversation

@EtaCassiopeia

Copy link
Copy Markdown
Collaborator

Deleting a port that has no imposter now behaves the same on both transports: it is a no-op, as in Mountebank and rift#1371.

Transport Before After
Remote, rift 0.22.0 (200 {}) succeeded succeeds
Remote, older engines (404) threw ImposterNotFound succeeds
Embedded (rift_delete_imposter → -1) threw EngineError succeeds

A delete that fails and leaves the imposter in place still throws EngineError. So does a remote response that is neither 2xx nor 404.

Changes

  • RemoteTransport.deleteImposter treats a 2xx or a 404 as success. Every other status goes through mapError. The class javadoc documents the 404 exception.
  • FfiCalls.deleteImposter: on -1 it captures the engine error first, because the probe clears last_error. It then calls rift_get_imposter. If the imposter is gone, the delete is a no-op; if it is still registered, the captured error is thrown. A failed engine delete always leaves the imposter registered (manager.rs removes it from the map last). The JDK 21 variant shares these sources.
  • Javadoc on Imposter.delete() (which had none) and RiftTransport.deleteImposter states the contract. docs/design/sdk-api.md is updated to match.

Release note (behaviour change)

Imposter.delete() on an imposter that is already gone now returns normally. Before, it threw ImposterNotFound (remote) or EngineError (embedded). To check whether an imposter exists, use rift.imposter(port).

Tests

  • RemoteTransportGateTest:
    • deletingAnImposterAnOlderEngine404sIsANoOp replaces the old deleteMissingImposterThrowsImposterNotFound. It failed before this change with ImposterNotFound.
    • New: deletingAnAbsentImposterOnA022EngineIsANoOp.
    • New: aFailedDeleteStillThrows, where a 500 throws EngineError(500).
  • EmbeddedTransportIT.deletingAnImposterTwiceIsIdempotent: deletes the same imposter twice, then a port that was never created. It failed before with EngineError: rift_delete_imposter: Imposter not found on port 49152.
  • New ImposterDeleteIT (conformance, SPAWN and EMBEDDED): create, delete twice, then rift.imposter(port) is empty.

Verification

RIFT_IT=1 ./mvnw -B -fae verify passes on JDK 21 against the rift 0.22.0 corpus, dylib and binary. ImposterDeleteIT also passes with CONFORMANCE_TRANSPORT=EMBEDDED.

Closes #308

🤖 Generated with Claude Code

rift 0.22.0 answers DELETE /imposters/:port for an absent port with 200 {}
(rift#1371, Mountebank's teardown), while rift_delete_imposter still returns
-1, so the same call succeeded remotely and threw embedded. Deleting an
absent imposter is now a no-op everywhere: remote also accepts the 404 older
engines send, and embedded probes rift_get_imposter after a -1, so a delete
that leaves the imposter registered still throws.

Closes #308
@EtaCassiopeia
EtaCassiopeia merged commit 083b161 into master Oct 16, 2026
18 checks passed
@EtaCassiopeia
EtaCassiopeia deleted the fix/rift-308-idempotent-imposter-delete branch October 16, 2026 20:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix: Imposter.delete() of an absent imposter succeeds over HTTP but throws embedded (rift#1371)

1 participant