lightninglabs / lightninglabs/taproot-assets

rpc: RPC handlers return codes.Unknown for predictable validation/lookup errors

Open
#2,086 6 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Go
Stars
525
Forks
150
Avg merge
2d 15h
Merged PRs (30d)
31

Description

Problem

Most tapd RPC handlers return plain fmt.Errorf / wrapped errors rather than status.Error(codes.X, ...). gRPC then surfaces these as codes.Unknown, leaving clients with no programmatic way to distinguish bad input from a missing resource from an internal failure — the error string is the only signal.

Caught while wiring typed errors through tap-sdk's REST transport (lightninglabs/tap-sdk#80). REST and gRPC now agree on the code, but that agreement is trivially Unknown == Unknown for every case we tried:

RPC Input Actual Expected
DecodeAddr "not-a-tap-addr" Unknown: unable to decode addr: address: invalid bech32m string InvalidArgument
DecodeProof [0x00, 0x01] Unknown: invalid raw proof, could not identify decoding format InvalidArgument
ExportProof zero asset_id + zero script_key Unknown: invalid script key: ... x coordinate 0x00..00 is not on the secp256k1 curve InvalidArgument (bad key) or NotFound (missing proof)

Why it matters

SDK callers (Go, tap-sdk REST, any grpc-gateway client) want to branch on the error type — retry on Unavailable, surface InvalidArgument to the user, treat NotFound as a non-error, etc. Today they have to string-match, which is fragile and locale-sensitive.

Proposal

Audit the RPC surface and replace plain fmt.Errorf returns in handler paths with status.Errorf(codes.X, ...). Obvious mappings:

  • Argument parsing/decoding (bech32, proof bytes, keys, hex/base64) → codes.InvalidArgument
  • Explicit "not in DB" lookups → codes.NotFound
  • Permission/macaroon → codes.PermissionDenied
  • Shutdown / context canceled → codes.Canceled / codes.Unavailable
  • Genuine internals (DB transaction failure, etc.) can keep the default Unknown/Internal

A stricter pattern is to introduce a small helper that wraps known sentinel errors into status codes at the RPC boundary, keeping handler internals free of grpc imports.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by auditing the tapd RPC handler paths for the named DecodeAddr, DecodeProof, and ExportProof cases, reproducing their current gRPC errors. Map predictable parsing, lookup, permission, shutdown, and internal failures to the proposed status codes, then verify that clients receive distinguishable codes without changing genuine internal failures.

Written by the indexing model from the issue text.

Assessment

Tech stack
go
Domain
api, backend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.