ValidationException: Unexpected from source

TL;DR — The table name in your PartiQL FROM clause contains characters the parser won't accept bare — usually a dash. Wrap the name in double quotes (SELECT * FROM "my-table"). Single quotes don't work: in PartiQL they mean a string literal, not an identifier.

What it means

ValidationException: Unexpected from source

The PartiQL parser reads FROM my-table as the identifier my followed by unexpected tokens — the dash isn't valid inside a bare identifier. DynamoDB table names may legally contain -, ., and _, so a perfectly valid table name can still be un-parseable in PartiQL until it's quoted. The same applies to names that collide with PartiQL keywords.

Why it happens

  • The table name contains a dash or dotusers-prod, app.events. Bare identifiers can't carry them.
  • Framework-generated table names — tooling that suffixes an environment or stage onto the table name (e.g. Todo-dev) is the classic way a dash gets in without you choosing it.
  • Querying an index without quotes — the "table"."index" form needs double quotes around both parts.
  • Single quotes instead of doubleFROM 'my-table' fails too: single quotes denote a string literal in PartiQL, not a name.

How to fix it

  1. Double-quote the table name:

    SELECT * FROM "users-prod" WHERE pk = 'USER#42'
  2. Double-quote both parts when querying an index:

    SELECT * FROM "users-prod"."email-index" WHERE email = 'ada@example.com'
  3. Keep single quotes for string values only — names in double quotes, values in single quotes. Mixing them up produces exactly this class of parse error.

  4. Quote defensively in generated statements — if your code interpolates table names into PartiQL, always emit them double-quoted; it's valid even when the name wouldn't strictly need it.

  5. Prefer native Query when possible. A Query/Scan request sidesteps PartiQL identifier rules entirely for simple reads.

Run it in DynoTable

DynoTable's PartiQL editor double-quotes table and index names automatically — run SELECT * FROM "my-table" with inline diagnostics before you paste the statement into SDK code. Open the table with ⌘K to confirm the exact table name (including dashes) from the sidebar.

When PartiQL parsing keeps failing, switch to the Query Builder for the equivalent native request. Profile switching (⌘P) and Test Connection on Settings → Profiles keep the statement pointed at the right table. See Connect to AWS and Install.

Sources

Reproduce it

A PartiQL statement whose FROM source is not a table name. The parser rejects it before it ever looks for a table, so this reproduces on any endpoint:

await client.send(new ExecuteStatementCommand({Statement: 'SELECT * FROM 123'}));

Real output:

ValidationException: Unexpected from source
HTTP 400

Contrast it with an unquoted but otherwise valid name: SELECT * FROM repro parses fine and fails later with ResourceNotFoundException if no such table exists. Unexpected from source is strictly a parse failure, so read it as a syntax signal, not a missing-table one.

References

Last verified 2026-07-13 against the official AWS documentation linked above.

Reproduced 2026-07-26 against DynamoDB Local 2.x with AWS SDK for JavaScript v3.1095.0 — the output above is verbatim.

Work with DynamoDB without the Console

A fast DynamoDB desktop client that runs the real SQL DynamoDB can’t — JOINs, GROUP BY, aggregates — with visual editing and an AI agent on your own Bedrock keys.

Free 30-day trial, no credit card — then the Free plan with no time limit.