> ## Documentation Index
> Fetch the complete documentation index at: https://paralens.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Troubleshoot ParaLens API Errors and Unexpected Results

> Fix common issues with the ParaLens API: invalid hash errors, 502 failures, missing USD values, and unexpected intent classifications.

Most issues with ParaLens fall into one of three categories: input errors (fixable on your side), upstream RPC failures (retryable), or valuation gaps (expected for obscure assets). This page covers the most common problems and how to resolve them.

<AccordionGroup>
  <Accordion title="I'm getting a 400 error">
    **Cause:** Invalid `tx_hash` format or unsupported chain.

    A `400 Bad Request` response means the API rejected your input before attempting any analysis. There are two common reasons:

    **Invalid hash format**

    The hash must be a 32-byte hex string with an `0x` prefix — 66 characters total:

    ```
    0x48f1494c42c04e0f6243970b1dfab3a2b17b9d27ba65682e68e384c11752cf18
    ```

    A quick way to check: count the characters. It should be `0x` (2 chars) + 64 hex characters = **66 total**. A hash that is too short, too long, or missing the `0x` prefix will be rejected.

    **Unsupported chain**

    Only Ethereum mainnet is currently supported. The `chain` field accepts the following aliases:

    | Value      | Meaning                     |
    | ---------- | --------------------------- |
    | `ethereum` | Ethereum mainnet            |
    | `mainnet`  | Ethereum mainnet            |
    | `eth`      | Ethereum mainnet            |
    | `1`        | Ethereum mainnet (chain ID) |

    Any other value will result in a `400` response with an error message indicating the chain is unsupported.
  </Accordion>

  <Accordion title="I'm getting a 502 error">
    **Cause:** Upstream RPC or analysis engine failure.

    A `502 Bad Gateway` response means ParaLens reached your request but encountered a failure in a downstream system — typically the Ethereum RPC node or the trace analysis pipeline. The error body will contain a message field:

    ```json theme={null}
    { "error": "RPC fetch failed: context deadline exceeded" }
    ```

    **These errors are retryable.** Wait a few seconds and try the request again. Most transient RPC failures resolve on a second or third attempt.

    Common triggers include:

    * **RPC congestion** — high network load can cause timeouts on the node side
    * **Very old transactions** — archive node lookups for historical blocks can be slower or occasionally fail
    * **Unusual trace formats** — some transactions produce non-standard execution traces that cause the analysis pipeline to fail

    If a `502` error persists for a specific transaction hash across multiple retries and over an extended period, the transaction may use a trace format that the current analysis engine does not support. In that case, the transaction cannot be analyzed at this time.
  </Accordion>

  <Accordion title="USD values show '—' or available: false">
    **Cause:** Pricing data is unavailable for one or more assets at the relevant block height.

    ParaLens looks up historical token prices at the exact block where the transaction was confirmed. If a price cannot be found, affected USD fields will reflect `available: false` (or display as `"—"` in formatted output).

    This is **expected behavior**, not an error. It commonly occurs for:

    * Obscure or low-liquidity tokens with no reliable price feed
    * Newly deployed contracts with no DEX liquidity at the time of the block
    * Assets that existed before on-chain price discovery was available

    **How to identify unpriced assets**

    Check the `economics.valuation.unpriced_assets` array in the response. It lists every asset for which pricing could not be resolved.

    **Workaround**

    USD fields in the response use the `DisplayMoney` structure: `{ text, available, reason }`. Always check `available` before rendering `text` — if `available` is `false`, `text` will be a placeholder (e.g., `"—"`) rather than a real value, and `reason` will explain why.

    For unpriced assets, fall back to the raw `quantity` and `asset_label` fields, which are always populated regardless of pricing availability.
  </Accordion>

  <Accordion title="The intent_kind doesn't match what I expected">
    **Cause:** Classification is based on structural proof derived from execution trace data, not from interpreting calldata or function names.

    ParaLens determines `intent_kind` by analyzing the actual state changes and call patterns in the transaction trace — not by reading the method selector or decoded input parameters. This means the classification reflects **what the transaction actually did**, which can differ from the label implied by the function name or UI context.

    A few things to check:

    **`classification.status`**

    If `status` is `Suspected` rather than `Proven`, the classification is a best-effort estimate based on partial structural evidence. The transaction did not produce a fully conclusive proof pattern.

    **`motifs[]`**

    The `motifs` array lists the structural patterns (e.g., token flow cycles, call graph shapes) that drove the classification. Reviewing these can help you understand why a specific `intent_kind` was assigned.

    **`classification.confidence`**

    A confidence value of `Low` indicates less certainty in the result. This can happen when a transaction involves multiple overlapping patterns or an unusual composition of operations.

    If the classification is consistently wrong for a class of transactions you care about, consider using `motifs` and raw flow data to build your own labeling layer on top of the API output.
  </Accordion>

  <Accordion title="actor_matches_signer is false — is this suspicious?">
    **Not necessarily.** A mismatch between the transaction signer and the economic actor is normal in many legitimate on-chain patterns.

    `actor_matches_signer: false` simply means the address that signed and submitted the transaction is not the same as the address that received economic benefit. This is common in:

    * **Aggregators** (1inch, 0x, Paraswap) — these protocols route execution through their own contracts, so the economic actor is often the router or a settlement contract rather than the EOA that signed
    * **Smart contract wallets** (Safe, Gnosis) — transactions are executed via a proxy contract, so the signer (an owner key) differs from the operating address
    * **MEV bots** — the signer is typically an EOA, but the actual logic and value capture occur inside a deployed contract

    **How to interpret the attribution object**

    The `attribution` object breaks down the relationship between these addresses:

    | Field               | Meaning                                                                      |
    | ------------------- | ---------------------------------------------------------------------------- |
    | `tx_signer`         | The EOA that signed and paid gas for the transaction                         |
    | `authority_subject` | The address with ultimate economic authority (often the same as `tx_signer`) |
    | `operating_subject` | The address that directly executed the operations                            |

    Use this object to trace the full chain of delegation rather than relying solely on `actor_matches_signer`.
  </Accordion>

  <Accordion title="realized_pnl.supported is false for an arbitrage transaction">
    **Cause:** `realized_pnl` is only available for fully self-closing atomic flows.

    Realized PnL requires that a position opens **and** closes entirely within the same transaction — meaning the same asset that flows out also flows back in, net-positive, with no reliance on external state carried across blocks.

    Some arbitrage strategies do not meet this requirement:

    * **Multi-hop arbitrage** that settles across more than one transaction
    * **Multi-block strategies** where a position is opened in one block and closed in a later one
    * **Complex position unwinds** that involve intermediate state (e.g., lending protocol positions)

    These patterns require multi-transaction PnL accounting, which ParaLens does not currently support. In these cases, `realized_pnl.supported` will be `false`.

    **Workaround**

    Use `economics.net_usd_before_gas` as an approximation of the value captured. This field reflects the net USD change for the economic actor before gas costs and is available for any transaction where pricing data is sufficient.
  </Accordion>

  <Accordion title="The API is slow">
    **Cause:** ParaLens fetches live trace data from an Ethereum RPC node on every request — response time is directly tied to RPC latency.

    There is no server-side cache. Each call to `/analyze` triggers a fresh trace fetch and full analysis pipeline run. This means latency varies based on:

    * **RPC response time** — the dominant factor; node load and geographic distance both contribute
    * **Transaction complexity** — transactions with many trace frames (`pipeline_stats.frames`) take longer to process because the analysis graph is larger

    **How to speed up repeated lookups**

    Because confirmed Ethereum transactions are immutable, the response for a given `tx_hash` will never change. **Cache responses on your side**, keyed by transaction hash. A confirmed transaction analyzed once does not need to be analyzed again.

    This is the single most effective optimization for applications that repeatedly display or process the same transactions.
  </Accordion>
</AccordionGroup>
