# Troubleshooting

## My task never matches

- Check that at least one worker has tags overlapping the task's tags.
- Verify workers are `available` (not paused).
- Check hard-veto rules that might exclude the worker.
- Call `GET /decisions?taskId=...` — the decision trace explains why each candidate was accepted or rejected.

## I get `401 unauthorized`

- Confirm you are using an `sk_test_...` or `sk_live_...` key, not a worker token.
- Check that the key has not been revoked in the console.
- Ensure the `Authorization: Bearer <key>` header is sent (SDKs do this automatically).

## I get `429 rate_limited`

- Read `Retry-After` and back off.
- Monitor `x-quota-task-rate-remaining` before you hit the limit.
- The SDK retries once automatically; if you still see 429s, reduce your call rate.

## Webhook signature verification fails

- Pass the **raw request body**, not parsed JSON.
- Do not decode or re-encode the body before verifying.
- Confirm your webhook secret matches the one in the console.
- Check that the signature timestamp is within 5 minutes of now.

## `POST /tasks` returned `400 validation_error`

Common causes:

- `priority` outside the allowed range.
- `tags` missing or empty.
- `workerId` provided on a field that expects it in the body, not the URL.

## Pagination loops forever

- Stop when `hasMore` is false, not when the page is empty.
- Use the `nextCursor` from the current page, not the previous one.

## Still stuck?

- Search the [API reference](/docs/api) for the exact endpoint.
- Inspect `client.decisions.list()` for match reasoning.
- Open a [docs issue](https://github.com/fivexer/sdks/issues/new) with the page URL and error code.
