Skip to content

Troubleshooting

Diagnose common Substreams authentication, package, cursor, reorg, stream, and limit issues.

Find the symptom your stream or sink shows, then work through its checks in order. Each entry names the likely cause first. If the checks do not resolve it, contact GraphOps support with the details listed at the end of this page.

Authentication fails

The stream is missing a valid API key, or the key is sent in the wrong place.

  1. Confirm the key was created for the organization that owns Substreams access.
  2. Confirm the key has not been revoked or rotated.
  3. For the CLI and sinks, confirm SUBSTREAMS_API_KEY is exported in the shell that runs the command.
  4. For raw gRPC clients, confirm every stream sends x-api-key: <GRAPHOPS_API_KEY> metadata.
  5. Remove extra quotes or whitespace from the stored secret value.
  6. Compare your setup with Authentication.

Package cannot be resolved

Standard Substreams tooling cannot load the package name, version, URL, or local .spkg reference.

  1. Confirm the package exists on substreams.dev or at the URL you provided.
  2. Pin an exact package version rather than a moving tag such as latest.
  3. Confirm an unpublished .spkg file is readable by the process running the consumer.
  4. Confirm the package supports the network endpoint you selected.

Module not found

The package does not expose the requested output module.

  1. Check the package page or manifest for the available modules.
  2. Match the module name exactly, including case.
  3. Confirm the module is a map module you can stream, not a store module.
  4. Regenerate client Protobuf types if the package output changed.

Stream disconnects

Long-running gRPC streams can disconnect because of network, client, or service conditions.

  1. Reconnect with exponential backoff and jitter.
  2. Resume from the latest committed cursor.
  3. Confirm the cursor is stored durably, not only in process memory.
  4. Reduce concurrency if many consumers reconnect at once.
  5. Log the endpoint, package reference, module name, cursor, and block number for each disconnect.

Duplicate data after reconnect

The consumer resumed from an earlier cursor, or replayed a block after a failed commit.

  1. Make output writes idempotent.
  2. Save the cursor only after the output commits.
  3. Store the cursor and output in one transaction when possible.
  4. Deduplicate by block number, block hash, ordinal, or a package-specific ID.

See Resume with cursors for the commit order.

Undo signal not handled

The stream sent a BlockUndoSignal, but the consumer did not revert its local state.

  1. Implement undo handling before you use reversible data for production state.
  2. Revert local state to the last valid block named in the signal.
  3. Save the signal's cursor after the rollback.
  4. Keep enough local history to undo recent writes.

See Cursors and reorgs for the recovery model.

Backfill is slow or expensive

The range is large, the output volume is high, or concurrency exceeds what your plan allows.

  1. Split the backfill into smaller ranges you can retry independently.
  2. Reduce concurrency.
  3. Use a narrower output module when possible.
  4. Track blocks processed, bytes out, bytes read, and bytes written.
  5. Check rates and limits in Usage and limits.

You need GraphOps to host the sink

Self-service Substreams assumes you run the sink. Hosted sinks are an enterprise option.

  1. Check whether a standard sink in your infrastructure fits; see Run a sink.
  2. If not, contact GraphOps from the platform about hosted sink options.

Need support

When you contact GraphOps support, include:

  • Organization name or ID.
  • Endpoint URL and chain ID.
  • Package reference and version.
  • Module name.
  • Start block, stop block, and latest committed cursor.
  • Approximate timestamp.
  • gRPC status or error message.
  • Whether the consumer saw BlockScopedData, BlockUndoSignal, or progress messages.

Never include your API key.

Next steps