ValidationException: Unexpected from source

TL;DR — 你 PartiQL FROM 子句里的表名含有解析器不接受的裸字符——通常是短横线。把名字用双引号包起来(SELECT * FROM "my-table")。单引号不行:在 PartiQL 里它表示字符串字面量,而不是标识符。

含义

ValidationException: Unexpected from source

PartiQL 解析器把 FROM my-table 读成标识符 my 后面跟着一堆意外的词法单元——短横线在裸标识符里是不合法的。DynamoDB 的表名合法地可以包含 -._,所以一个完全合法的表名在 PartiQL 里仍然可能无法被解析,直到你给它加上引号。与 PartiQL 关键字冲突的名字也是同理。

为什么会发生

  • 表名含有短横线或点——users-prodapp.events。裸标识符带不了它们。
  • 框架生成的表名——那些把环境或阶段名后缀拼到表名上的工具(例如 Todo-dev),是短横线在你没主动选择的情况下混进来的经典途径。
  • 查询索引时没加引号——"table"."index" 这种写法需要两部分都加双引号。
  • 用了单引号而不是双引号——FROM 'my-table' 同样会失败:在 PartiQL 里单引号表示字符串字面量,而不是名字。

如何修复

  1. 给表名加双引号:

    SELECT * FROM "users-prod" WHERE pk = 'USER#42'
  2. 查询索引时两部分都加双引号:

    SELECT * FROM "users-prod"."email-index" WHERE email = 'ada@example.com'
  3. 单引号只留给字符串值——名字用双引号,值用单引号。把两者搞混,产生的正是这一类解析错误。

  4. 在生成语句时防御性地加引号——如果你的代码把表名插值进 PartiQL,就总是把它们双引号包起来;即使某个名字严格来说并不需要,这么写也是合法的。

DynoTable 的 PartiQL 编辑器会替你处理标识符的引号——针对的正是这一类解析错误,并带内联诊断和快速修复;而如果你宁愿完全绕开 PartiQL 的解析,DynamoDB Expression Builder 会给出等价的原生 Query/Scan 请求。

在 DynoTable 中运行

DynoTable 的 PartiQL 编辑器会自动用双引号引用表和索引名称 — 在将语句粘贴到 SDK 代码中之前运行 SELECT * FROM "my-table" 并进行内联诊断。使用 ⌘K 打开表格,从侧边栏确认确切的表格名称(包括破折号)。当 PartiQL 解析持续失败时,切换到 Query Builder 以获得等效的本机请求。Settings → Profiles上的 Profile 切换 (⌘P) 和 Test Connection 使语句保持指向正确的表。参见连接 AWS安装

来源

复现方法

PartiQL 语句,其 FROM 源不是表名。解析器在查找表之前会拒绝它,因此这会在任何端点上重现:

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

实际输出:

ValidationException: Unexpected from source
HTTP 400

将其与未加引号但有效的名称进行对比:SELECT * FROM repro 解析得很好,如果不存在这样的表,则稍后会失败,并使用 ResourceNotFoundExceptionUnexpected from source 严格来说是一个 解析 失败,因此将其视为语法信号,而不是缺失表信号。

相关错误

参考资料

最后核实于 2026-07-13,依据上方链接的 AWS 官方文档。

2026-07-26 针对 DynamoDB Local 2.x 与 AWS SDK for JavaScript v3.1095.0 复现——上方输出为原样照录。

无需控制台即可使用 DynamoDB

一款快速的 DynamoDB 桌面客户端,可运行 DynamoDB 无法执行的真正 SQL——JOINs、GROUP BY、聚合——并支持可视化编辑和运行在你自己的 Bedrock 密钥上的 AI agent。

30 天免费试用,无需信用卡 — 之后为无时间限制的免费版。