unionlabs/union · warning · Error

Packet not found

Error message

Packet not found

What it means

Thrown in the writeData callback of a TanStack Query (Svelte) that polls a GraphQL v2_packets query every 30 seconds for a given packet_hash. It fires when the query succeeds but returns an empty v2_packets array, meaning the backend currently has no packet with that hash. The '// TODO: make tagged error' comment shows the authors know this generic Error conflates 'not indexed yet' with 'does not exist'.

Source

Thrown at app2/src/lib/queries/packet-details.svelte.ts:77

            timestamp
            transaction_hash
            chain {
              universal_chain_id
              rpc_type
            }
          }
          
        }
      }
    `),
    variables: { packet_hash: packetHash },
    refetchInterval: "30 seconds",
    writeData: data => {
      data.pipe(
        Option.map(d => {
          if (d.v2_packets.length === 0) {
            // TODO: make tagged error
            throw new Error("Packet not found")
          }
          return d.v2_packets[0]
        }),
        Option.tap(packet => {
          packetDetails.data = Option.some(packet)
          return Option.some(packet)
        }),
      )
    },
    writeError: error => {
      packetDetails.error = error
    },
  })

View on GitHub (pinned to 031785bb6d)

Solutions

  1. Verify the hash is the full 66-character 0x-prefixed value returned by the sending transaction and belongs to the network the GraphQL endpoint indexes
  2. If the packet was just sent, treat this as transient: the 30-second refetchInterval recovers automatically once the indexer ingests the packet
  3. Run the v2_packets query directly in the GraphQL playground with the same packet_hash variable to confirm whether the row exists server-side
  4. Replace the generic Error with a tagged error (per the TODO) so UI code can distinguish 'pending indexing' from 'never exists' and stop retrying

Example fix

// before
if (d.v2_packets.length === 0) {
  // TODO: make tagged error
  throw new Error("Packet not found")
}
return d.v2_packets[0]

// after
export class PacketNotFoundError extends Error {
  readonly _tag = "PacketNotFoundError" as const
}
if (d.v2_packets.length === 0) {
  throw new PacketNotFoundError()
}
return d.v2_packets[0]
Defensive patterns

Strategy: retry

Validate before calling

const isPacketHash = (h: string) => /^0x[0-9a-fA-F]{64}$/.test(h)

if (!isPacketHash(packetHash)) {
  throw new Error(`Invalid packet hash: ${packetHash}`)
}
// only then start the polling query

Type guard

const hasPacket = (d: { v2_packets: unknown[] } | undefined): d is { v2_packets: [unknown, ...unknown[]] } =>
  (d?.v2_packets?.length ?? 0) > 0

Try / catch

try {
  await queryClient.refetchQueries({ queryKey: ["packetDetails", packetHash] })
} catch (e) {
  if (e instanceof Error && e.message === "Packet not found") {
    // transient: packet not indexed yet — keep polling, do not surface as fatal
    return
  }
  throw e
}

Prevention

When it happens

Trigger: Querying packet details with (a) a mistyped or truncated hash, (b) a packet that was just broadcast and is not yet indexed (the throw repeats on each 30s refetch until the indexer catches up), or (c) a hash from a different network than the GraphQL endpoint serves.

Common situations: Fresh cross-chain transactions where the packet lands on-chain seconds before the subgraph sees it; copying a hash without the 0x prefix or with missing characters; pointing the app at testnet data while using a mainnet hash.


AI-assisted analysis of unionlabs/union@031785bb6d (2026-08-16). Data as JSON: /api/errors/2020c7dde0361bb5. Report an issue: GitHub.