Redshift API: 200 Means Accepted, Not "Your Query Worked"

The video explains that ExecuteStatement on Amazon Redshift's Data API returns 200 for any accepted query, even one with a typo, and returns only an Id. It then covers the polling and cell-decoding habits that make results trustworthy.

2:07 video3 min readWatch on YouTube

A common assumption is that a 200 response from Amazon Redshift's Data API means the query worked. This short video, part of a series on Claude plugins, explains why that is wrong. A 200 from ExecuteStatement means only that the query was accepted. Whether it ran correctly is a separate question, answered later through a different call.

200 means accepted, not correct

The Data API does not return rows when you submit SQL. It returns an Id, a handle to check later. The video makes the point with a blunt example: send SQL containing a typo and ExecuteStatement still returns 200. The failure appears only when you poll DescribeStatement and see a status of FAILED. It never shows up in the response to the call that submitted the query.

Set the region and connection target first

Before any call is made, two things have to be set. The first is the region, which is baked into the endpoint hostname. The second is a connection target, which takes one of three shapes:

  • a workgroup name for Redshift Serverless,
  • a cluster plus a database user for provisioned access, or
  • a secret for Secrets Manager.

With the workgroup set, the video submits a real query: the top twenty events from the past month, grouped by name. ExecuteStatement hands back exactly one thing, the Id.

Poll until the statement reaches a terminal state

The next step is to poll that same Id with DescribeStatement until the statement reaches FINISHED. Only then should you check HasResultSet before calling GetStatementResult, because a write statement can finish with nothing to page through.

The video adds two cautions. FINISHED alone does not prove the SQL was clean, since the same status field can read FAILED instead, and only DescribeStatement ever says so. And a statement sitting at STARTED is not stuck. Waiting through that state is exactly what the poll loop is for.

Decode each cell correctly

One habit carries beyond this single query: decode each result cell with to_entries[0].value rather than a plain .value. A plain .value silently returns nothing, which is easy to miss because no error is raised.

The carry-out

The video boils every Redshift query Claude runs down to two habits. First, poll DescribeStatement to a terminal state before ever calling GetStatementResult. Second, decode cells with to_entries[0].value. With those in place, a 200 from ExecuteStatement stops being treated as proof of anything beyond acceptance.

Key takeaways

  • A 200 from ExecuteStatement means the query was accepted, not that it succeeded.
  • ExecuteStatement returns an Id, not rows or a result.
  • Failures surface only as a FAILED status on DescribeStatement.
  • Set the region and a connection target (workgroup, cluster plus database user, or secret) before any call.
  • Poll to a terminal state, then check HasResultSet before calling GetStatementResult.
  • A statement at STARTED is not stuck; keep polling.
  • Decode result cells with to_entries[0].value, not a naive .value.

Try it yourself

Give Claude this prompt: "Query my Redshift Serverless workgroup, find the top twenty events from the past month, grouped by name." Then watch three things. Does it set the region and workgroup before making any call? Does it poll DescribeStatement to a terminal state before calling GetStatementResult? And does it read result cells with to_entries[0].value instead of a naive .value that comes back empty?

Chapters

  1. 0:00A 200 from Redshift means my query worked. Right?
  2. 0:10200 means accepted, not correct
  3. 0:29Region + RS_TARGET, then submit
  4. 0:50Finished isn't proof it succeeded
  5. 1:21Carry-out
  6. 1:39Your turn
  7. 2:03Outro
Full transcript(auto-generated, with timestamps)

A 200 from Redshift means my query worked. Right?

[0:00]Someone assumes a 200 back from Redshift means their query worked. It doesn't. 200 only means the query began. Whether it actually finished comes later. So, did it really work? Submit a query and

200 means accepted, not correct

[0:11]Redshift's Data API hands back an ID, not rows, not a result, just an ID to check later. Send SQL with a typo and execute statement still returns 200. Only polling describe statement later reveals status failed. The failure never shows up in the response to the call that submitted it. Two things have to be set

Region + RS_TARGET, then submit

[0:30]Before any call: the region baked into the endpoint hostname and a connection target in one shape, a workgroup name for serverless, a cluster plus a database user for provisioned access, or a secret for Secrets Manager. Set the workgroup and submit the real query, the top 20 events from the past month grouped by name, and execute statement hands back exactly one thing, an ID. Poll that same ID with describe

Finished isn't proof it succeeded

[0:51]Statement until it reaches finished, then check has result set before calling get statement result. A write statement can finish with nothing to page. But, finished alone doesn't mean the SQL was clean. That same field can read failed instead, and only describe statement, never the original call, ever says so. A statement still sitting at started isn't stuck, either. That's what the poll loop is for. One habit that carries past this one query, decode each cell with to entries bracket zero.value. A plain .value silently returns nothing.

Carry-out

[1:21]Every Redshift query cloud runs turns on two habits. Poll describe statement to a terminal state before ever calling get statement result, and decode each cell with to entries bracket zero.value instead of a naive .value get those right and a 200 from execute statement stops meaning anything it doesn't. Your

Your turn

[1:39]Turn. Here's the prompt. Read it with me. Query my Redshift serverless workgroup, find the top 20 events from the past month grouped by name. Watch three things. Does it set the region and the workgroup before making any call? Does it poll describe statement to a terminal state before ever calling get statement result? And does it read the result cells with to entries bracket zero.value instead of naive.value that comes back empty. Lay them in for bear. Claude Redshift API Lay them in for

Outro

[2:05]Bear.

More from Claude

Humanitarians AI Lyrical Literacy Project