Skip to content

Expose standard Rust traits on FFI error types#1485

Merged
spacebear21 merged 2 commits intopayjoin:masterfrom
spacebear21:ffi-expose-standard-traits
Apr 17, 2026
Merged

Expose standard Rust traits on FFI error types#1485
spacebear21 merged 2 commits intopayjoin:masterfrom
spacebear21:ffi-expose-standard-traits

Conversation

@spacebear21
Copy link
Copy Markdown
Collaborator

@spacebear21 spacebear21 commented Apr 15, 2026

This fixes the string representation of the FFI errors to use the Rust Display string instead of an opaque Instance of *Error message. See #1264 (comment) for more context.

Discovered and authored with Claude.

Pull Request Checklist

Please confirm the following before requesting review:

@spacebear21 spacebear21 requested a review from chavic April 15, 2026 21:31
@spacebear21 spacebear21 mentioned this pull request Apr 15, 2026
9 tasks
@coveralls
Copy link
Copy Markdown
Collaborator

coveralls commented Apr 15, 2026

Coverage Report for CI Build 24527851470

Coverage remained the same at 84.38%

Details

  • Coverage remained the same as the base build.
  • Patch coverage: No coverable lines changed in this PR.
  • No coverage regressions found.

Uncovered Changes

No uncovered changes found.

Coverage Regressions

No coverage regressions found.


Coverage Stats

Coverage Status
Relevant Lines: 12766
Covered Lines: 10772
Line Coverage: 84.38%
Coverage Strength: 413.48 hits per line

💛 - Coveralls

@spacebear21
Copy link
Copy Markdown
Collaborator Author

The dart error here looks unrelated to the changes in this PR, @chavic can you confirm?

@codaMW
Copy link
Copy Markdown
Contributor

codaMW commented Apr 16, 2026

Reviewed the changes. Exposing Display, Error, and Debug on FFI error types is the right move, this makes them usable with anyhow and ? in Rust glue code, and improves error messages for FFI consumers.

One small question: the PR description mentions fixing "Instance of *Error" strings. Is this primarily improving the Dart/Kotlin/Swift binding experience? Might be helpful to note in the commit body.

Regarding the unrelated Dart CI failure, agreed it's pre-existing and not related to this change.
utACK.

@benalleng
Copy link
Copy Markdown
Collaborator

The dart error here looks unrelated to the changes in this PR, @chavic can you confirm?

This seems to relate to the errors being turned to "Exception" like in the early stage of #1428 (comment)

@spacebear21 spacebear21 force-pushed the ffi-expose-standard-traits branch from 07df5e4 to 54e06c7 Compare April 16, 2026 18:40
@spacebear21
Copy link
Copy Markdown
Collaborator Author

This seems to relate to the errors being turned to "Exception" like in the early stage of #1428 (comment)

Yep, confirmed that updating uniffi-dart to the latest git rev fixes the issue and added this in a9e0cab.

@spacebear21 spacebear21 force-pushed the ffi-expose-standard-traits branch from 54e06c7 to 4d2855c Compare April 16, 2026 18:45
Uniffi-Dart/uniffi-dart#120 fixed an issue where
uniffi-dart substitutes `Error` with `Exception` but didn't correctly
reference the updated name in method signatures, etc.
This fixes the string representation of the FFI errors to use the Rust
Display string instead of an opaque `Instance of *Error` message in
downstream language bindings.
@spacebear21 spacebear21 requested a review from benalleng April 16, 2026 19:21
Copy link
Copy Markdown
Collaborator

@benalleng benalleng left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TACK 4d2855c

I added some dummy Display tests to visualize the errors in python with the following tests.

Python Display Tests
class TestErrorDisplay(unittest.TestCase):
    def test_address_parse_error_display(self):
        try:
            payjoin.ReceiverBuilder(
                "not-an-address",
                "https://example.com",
                payjoin.OhttpKeys.decode(bytes.fromhex(
                    "01001604ba48c49c3d4a92a3ad00ecc63a024da10ced02180c73ec12d8a7ad2cc91bb483824fe2bee8d28bfe2eb2fc6453bc4d31cd851e8a6540e86c5382af588d370957000400010003"
                )),
            )
            self.fail("expected error")
        except payjoin.ReceiverBuilderError as e:
            msg = str(e)
            self.assertNotIn("Instance of", msg)
            self.assertTrue(len(msg) > 0)

    def test_sender_input_error_display(self):
        uri = payjoin.Uri.parse(
            "bitcoin:tb1q6d3a2w975yny0asuvd9a67ner4nks58ff0q8g4?pj=https://example.com/pj"
        ).check_pj_supported()
        try:
            payjoin.SenderBuilder("not-a-psbt", uri)
            self.fail("expected error")
        except payjoin.SenderInputError as e:
            self.assertNotIn("Instance of", str(e))

    def test_pj_parse_error_display(self):
        try:
            payjoin.Uri.parse("not-a-uri")
            self.fail("expected error")
        except payjoin.PjParseError as e:
            print(f"\ntype={type(e).__name__}")
            print(f"{str(e)!r}")
            print(f"{repr(e)!r}")
            self.assertIn("Error parsing the payjoin URI", str(e)) 

Saw this response.

$ uv run python -m unittest test.test_payjoin_unit_test.TestErrorDisplay.test_pj_parse_error_display -v test_pj_parse_error_display (test.test_payjoin_unit_test.TestErrorDisplay.test_pj_parse_error_display) ... 
type=PjParseError
'Error parsing the payjoin URI: invalid BIP21 URI'
'PjParseError { msg: "invalid BIP21 URI" }'
ok

Not right now but I think it would be really nice to get some error Display test coverage in payjoin soon maybe as a v1.1 milestone

Copy link
Copy Markdown
Contributor

@caarloshenriq caarloshenriq left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tACK 4d2855c

Ran the Python Display tests from @benalleng locally after regenerating the bindings:

test_address_parse_error_display ... ok
test_pj_parse_error_display ...

type=PjParseError
'Error parsing the payjoin URI: invalid BIP21 URI'
'PjParseError { msg: "invalid BIP21 URI" }'
ok
test_sender_input_error_display ... ok

@spacebear21 spacebear21 merged commit 5dcce43 into payjoin:master Apr 17, 2026
23 checks passed
@spacebear21
Copy link
Copy Markdown
Collaborator Author

I think it would be really nice to get some error Display test coverage in payjoin soon maybe as a v1.1 milestone

Agreed, we should also start thinking about a strategy for cross-testing these things across the all downstream language bindings. Maybe we can pull out test inputs and expected results into shared test vectors to loop over in each language's test module, or something like that.

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.

5 participants