错误参考
类型化的框架失败是带有稳定机器可读 type 代码的 FlueError 子类,加上下面记录的两个普通 Error 类(AgentRunError 和 ResultUnavailableError)。取消以名为 AbortError 的 DOMException 拒绝。编程入口点的误用(在运行时配置之前调用 dispatch() 或 init()、空实例 ID)抛出普通 Error,其 [flue] 前缀的消息是说明文,不是 API。错误类从 @flue/runtime 导出,有两个例外:Cloudflare 绑定表面在 @flue/runtime/cloudflare 上,持久化存储类在 @flue/runtime/adapter 上。
Flue Agent SDK 的错误类(FlueApiError、FlueExecutionError、流错误)在 SDK 错误参考中有文档。它们包装本页定义的相同线路信封和结算形状。
FlueError
class FlueError extends Error {
readonly type: string;
readonly details: string;
readonly dev: string;
readonly meta: Record<string, unknown> | undefined;
readonly cause: unknown;
}
框架类型化错误的基类。用 err instanceof FlueError 区分 Flue 失败和任意错误,然后用具体子类或 type 字段收窄。
type— 稳定的 snake_case 标识符,每个子类一个常量。这是机器可读的契约;在代码和遥测中匹配它。message— 一句调用者安全的话。说明文,不是 API:消息字符串可能在版本间变化。details— 更长的调用者安全说明文,关于请求和调用者可以做什么。始终在线路上渲染。当类没有更多可说的时为''。dev— 面向开发者的说明文:可用替代方案、文件系统布局、源级修复指令。仅在本地开发中在线路上渲染。当类没有特定于开发的内容时为''。meta— 可选的结构化数据。仅由记录为携带它的子类设置;设置时在每种模式下都包含在线路上。cause— 包装时的底层错误。服务端记录;从不在线路上发送。name— 不是判别器。大多数子类报告'FlueError'或'FlueHttpError';只有少数覆盖它。使用instanceof或type。
HTTP 基类(FlueHttpError,添加 readonly status: number 和 readonly headers: Record<string, string> | undefined)不导出。它的两个导出子类 AgentInstanceNotFoundError 和 AgentInstanceExistsError 通过它暴露 status 和 headers。
HTTP 错误信封
来自智能体路由、挂载的 createAgentRouter() 应用或频道路由器的每个错误响应携带一个 JSON 主体形状:
{
"error": {
"type": "stream_not_found",
"message": "Event stream \"...\" was not found.",
"details": "Streams are created when their agent instance receives its first prompt.",
"dev": "...",
"meta": {}
}
}
type、message、details— 始终存在。dev— 仅当服务器在本地开发中运行(flue dev、flue run)且错误类填充了它时存在。它的存在不是可靠的模式信号:类设置了dev: ''的错误在每种模式下都省略该字段。meta— 无论错误类是否设置它,在开发和生产中都存在。ref— 服务器铸造的关联引用(err_+ ULID),仅当服务器记录了错误时存在(下面的两个 500 类渲染)。相同值作为flue-error-ref响应头发送,并前缀匹配的服务端日志行。在未记录的调用者错误(4xx)响应上从不出现。cause和堆栈跟踪——从不出现。
状态解析:
- HTTP 类型的
FlueError用其类拥有的状态(下面按类型列出)加上任何类拥有的头(405 上的Allow、503 上的Retry-After: 1)渲染。 - 逃逸到路由的非 HTTP
FlueError用状态 500 渲染其类型化信封并在服务端记录,新的ref将响应与日志行关联。 - 任何非
FlueError的抛出值渲染为通用 500internal_error信封。原始错误在服务端完整记录,除了ref之外没有任何内容到达线路。
每个错误响应还携带 content-type: application/json、x-content-type-options: nosniff 和 cross-origin-resource-policy: cross-origin。
两个路由响应刻意省略信封:HEAD 对话读取仅用状态和头回答错误(无主体——flue-error-ref 头在记录的渲染上仍然存在),客户端中止的长轮询读取返回状态 499 和空主体。SSE 或长轮询头发送后的中途失败在没有信封的情况下终止流。
关联生产环境 500 错误
引用 ref(来自 error.ref 或 flue-error-ref 头——该头在无主体响应和吞没主体的中介中存活)。匹配的服务端日志行以 [flue] [err_…] 开头并携带完整错误及其原因链和堆栈;因为 ref 是 ULID,单独的 ref 也界定了搜索的时间窗口。当失败的请求携带了 W3C traceparent 时,日志行在 ref 旁边记录它,因此传播跟踪上下文的调用者可以将失败加入自己的跟踪。ref 仅存在于同步渲染中:在 202 接纳之后失败的提交没有 ref——它的句柄是 submissionId,由 submission_settled 记录、SDK 的 FlueExecutionError.targetId 和相应的 [flue:submission-…] 日志行共享。
路由错误类型
智能体路由产生的线路 type 代码及其状态。只有 agent_instance_not_found 和 agent_instance_exists 有可导入的类;其余在 error.type 上匹配。路由本身在流协议参考中有文档。
invalid_request— 400。畸形请求:错误的 URL 或参数形状、空的 instance-id 段、无效的调度载荷、uid条件与initialData结合,或创建数据未通过智能体的initialDataSchema。details说明具体原因。invalid_json— 400。请求主体存在但无法解析为 JSON。details包含解析器的报告。unsupported_media_type— 415。请求主体存在但没有Content-Type: application/json头。method_not_allowed— 405。响应携带Allow头列出接受的方法。route_not_found— 404。没有路由匹配方法和路径。已注册的路由不会被枚举。stream_not_found— 404。对从未接收过提示的实例的对话流读取。attachment_not_found— 404。未知的附件 ID,或属于非默认对话的附件。history_cursor_not_found— 410。有界历史读取的before或from游标由早期一代对话流发出(流已被重置并重新增长),或指向已消失的消息。在meta.cursor中携带被拒绝的游标。不带游标重新读取最新窗口。agent_instance_not_found— 404。参见AgentInstanceNotFoundError。agent_instance_exists— 409。参见AgentInstanceExistsError。runtime_unavailable— 503。本地开发运行时正在重新加载、排空或加载失败。携带Retry-After: 1和meta.state('loading' | 'draining' | 'failed');在开发模式下dev携带底层加载失败。internal_error— 500。意外服务器错误的通用编辑。
发送的接纳——通过 HTTP 或通过 dispatch() 和 init().dispatch()——也以 type: 'invalid_request' 拒绝载荷误用:uid 字符串条件与 initialData 结合、创建数据未通过智能体的 initialDataSchema,或非函数的 agent 参数。该类(InvalidRequestError)不导出;用 instanceof FlueError 和 type 字段匹配。
内部不变量和持久化失败有自己的代码,可以出现在 500 信封或结算错误中:conversation_record_invariant(无可导入类)、@flue/runtime/adapter 类携带的存储代码(AttachmentConflictError、AttachmentIntegrityError、ConversationStreamStoreError、PersistedFormatVersionError),以及 cloudflare_ai_binding_error(@flue/runtime/cloudflare 上的 CloudflareAIBindingError)。
app.ts 中编写的路由和中间件拥有自己的响应;上面的信封和状态词汇仅适用于框架拥有的路由。
AgentInstanceExistsError
class AgentInstanceExistsError extends FlueError {
// type: 'agent_instance_exists', status: 409
readonly uid: string | undefined;
}
仅创建发送(uid: null)——带有条件的 dispatch() 或 init().dispatch(),或等效的 HTTP 主体字段——命名了已存在的实例。在接纳时同步抛出;触发时不创建任何持久内容。通过 HTTP 以状态 409 渲染;编程上返回的 promise 以类实例拒绝。
uid— 现有 incarnation 的 uid,可直接用作继续条件。对于 uid 发布之前创建的实例为undefined。uid 也作为meta.uid在线路信封上(并出现在details说明文中),因此 HTTP 调用者可以继续现有实例而无需单独查找。
AgentInstanceNotFoundError
class AgentInstanceNotFoundError extends FlueError // type: 'agent_instance_not_found', status: 404
仅继续发送(uid: '<string>')——带有条件的 dispatch() 或 init().dispatch(),或等效的 HTTP 主体字段——命名了不存在或 uid 不匹配的实例。两种情况产生相同的错误:对持有 uid 条件的调用者来说,已知的 incarnation 无论如何都不存在。在接纳时同步抛出;触发时不创建任何持久内容。通过 HTTP 以状态 404 渲染;编程上返回的 promise 以类实例拒绝。不带 uid 发送以无条件投递。
也是对指向不存在实例的 init().read() 的拒绝:读取等待结算,从未联系过的实例没有可结算的内容,因此未命中快速失败而不是永远等待。
AgentRunError
class AgentRunError extends Error {
readonly outcome: 'failed' | 'aborted';
readonly submissionId: string;
}
等待的 init().read() 调用的拒绝,其提交结算为 failed 或 aborted。不是 FlueError。
outcome— 非完成的结算结果。submissionId— 已结算的提交。cause— 结算的序列化错误(结算错误形状下的{ name?, message, type?, details?, meta? }形状),当结算携带一个时。
signal 已触发的 read() 调用以信号的原因而非 AgentRunError 拒绝——默认是名为 AbortError 的 DOMException。这仅是读取的本地取消;提交本身继续运行并独立结算。要持久停止智能体的工作,调用 abort()。
AttachmentConflictError
// from '@flue/runtime/adapter'
class AttachmentConflictError extends FlueError // type: 'attachment_conflict'
附件 ID 被不同内容、元数据或所有权重用。从 @flue/runtime/adapter 导出,与它保护的存储契约一起;参见数据持久化 API。在存储操作中触发,不是 HTTP 类别;逃逸到路由的以 500 渲染并带有自己的类型代码。meta 携带 path 和 attachmentId。
AttachmentIntegrityError
// from '@flue/runtime/adapter'
class AttachmentIntegrityError extends FlueError // type: 'attachment_integrity'
附件字节未通过完整性验证。从 @flue/runtime/adapter 导出,与它保护的存储契约一起;参见数据持久化 API。在存储操作中触发,不是 HTTP 类别;逃逸到路由的以 500 渲染并带有自己的类型代码。meta 携带 attachmentId 和 reason('size' | 'digest' | 'chunks')。
AttachmentNotAvailableError
class AttachmentNotAvailableError extends FlueError // type: 'attachment_not_available'
当委派的任务引用了调用会话对话中不可见的附件 ID 时,由 harness 操作抛出。meta 携带 attachmentId。
CloudflareAIBindingError
// from '@flue/runtime/cloudflare'
class CloudflareAIBindingError extends FlueError {
// type: 'cloudflare_ai_binding_error'
constructor(options: { message?: string; status?: number; statusText?: string; body?: string });
}
Workers AI 绑定请求失败。从 @flue/runtime/cloudflare 导出;特定于 Workers AI 绑定路径,不在根桶中。Provider 响应主体在 message(限制为 2000 字符)以及 details 中,因为重试和溢出分类读取持久化的助手错误消息。meta 携带 status 和 statusText(当已知时),加上 413 响应上的 reason: 'request_too_large',以便遥测可以区分自愈上下文溢出和绑定中断。构造函数是公开的,因此应用可以在针对安装的运行时的回归测试中构建实例。
ConversationStreamStoreError
// from '@flue/runtime/adapter'
class ConversationStreamStoreError extends FlueError // type: 'conversation_stream_store_failure'
规范对话流操作被拒绝;流保持不变。从 @flue/runtime/adapter 导出,与它保护的存储契约一起;参见数据持久化 API。在存储操作中触发,不是 HTTP 类别;逃逸到路由的以 500 渲染并带有自己的类型代码。meta 携带 operation、path 和 reason。
相关的 conversation_record_invariant 代码(违反流契约的持久化对话记录)没有导出类。
DelegationDepthExceededError
class DelegationDepthExceededError extends FlueError // type: 'delegation_depth_exceeded'
当嵌套的 task() / harness 工具委派链超过最大深度时,由 harness 操作抛出。message 包含限制。
InstrumentationAlreadyInstalledError
class InstrumentationAlreadyInstalledError extends FlueError // type: 'instrumentation_already_installed'
在同类检测所有者活跃时调用了 instrument()。先处理活跃的那个。
OperationFailedError
class OperationFailedError extends FlueError // type: 'operation_failed'
harness 操作——FlueHarness 和 FlueSession 上的 prompt()、skill()、task()、shell() 或 compact()——运行了但未完成:底层模型调用出错,或持久输入无法持久化或恢复。meta 携带 operation 和 reason(解包装的失败文本,也嵌入在 message 中;两者都是说明文,不是 API)。
PersistedFormatVersionError
// from '@flue/runtime/adapter'
class PersistedFormatVersionError extends FlueError // type: 'persisted_format_version_unsupported'
数据库记录了此运行时不支持的格式版本:由更新的 Flue 版本标记(回滚后)或携带无法识别的版本标记。在打开存储时抛出,在启动时。从 @flue/runtime/adapter 导出,与它保护的存储契约一起;参见数据持久化 API。meta 携带 storedVersion 和 supportedVersion。
ResultUnavailableError
class ResultUnavailableError extends Error {
readonly reason: string;
readonly assistantText: string;
}
当调用设置了 options.result 且模型调用了框架的放弃工具而不是产生符合模式的数据时,由 prompt()、skill() 和 task() 抛出。不是 FlueError。
reason— 模型提供的解释。assistantText— 放弃前积累的助手对话记录。
SandboxOperationUnsupportedError
class SandboxOperationUnsupportedError extends FlueError // type: 'sandbox_operation_unsupported'
沙盒适配器在修改文件系统之前拒绝了它不实现的操作或选项集。meta 携带 operation、provider 和 options。参见沙盒 API 参考。
SessionBusyError
class SessionBusyError extends FlueError // type: 'session_busy'
harness 操作——prompt()、skill()、task()、shell() 或 compact()——在会话已在运行一个时被调用。会话一次运行一个操作;为并行分支打开另一个会话。
SessionNotFoundError
class SessionNotFoundError extends FlueError // type: 'session_not_found'
harness 内部的会话查找失败。公共 harness 操作获取或创建默认会话,不会命中它。
SkillDefinitionValidationError
class SkillDefinitionValidationError extends FlueError // type: 'skill_definition_validation'
defineSkill() 接收到了无效的定义。meta.issues 携带 ValidationIssue[]。
SkillNotRegisteredError
class SkillNotRegisteredError extends FlueError // type: 'skill_not_registered'
skill(name) 命名了初始化时在会话沙盒中未发现的技能。从 SKILL.md 导入的打包技能引用绕过发现。
SubagentNotDeclaredError
class SubagentNotDeclaredError extends FlueError // type: 'subagent_not_declared'
task({ agent }) 命名了智能体声明中不存在的子智能体。
SubmissionAbortedError
class SubmissionAbortedError extends FlueError // type: 'submission_aborted'
持久提交结算的终端错误:它成为 submission_settled 记录和事件的 error(下面的结算错误形状)并拒绝等待的结算观察者(init().read()、SDK 的 wait())。实例的工作被中止(路由的 POST .../abort,或 init() 句柄的 abort())。中止停止实例的所有进行中和排队工作。中止是不同的终端结果,不是失败:已提交其终端记录的提交从不被中止,输掉完成响应竞赛的中止结算为完成。
SubmissionInterruptedError
class SubmissionInterruptedError extends FlueError // type: 'submission_interrupted'
持久提交结算的终端错误:它成为 submission_settled 记录和事件的 error(下面的结算错误形状)并拒绝等待的结算观察者(init().read()、SDK 的 wait())。在提交的输入应用之前,每次处理尝试都被中断(进程崩溃、重启、关闭);共享的尝试预算在从未开始模型调用的情况下耗尽。它反映了智能体的 durability 配置;参见持久性指南了解尝试和超时模型。meta 携带 phase: 'retry_exhausted_before_input'、attemptCount 和 maxAttempts。
SubmissionRetryExhaustedError
class SubmissionRetryExhaustedError extends FlueError // type: 'submission_retry_exhausted'
持久提交结算的终端错误:它成为 submission_settled 记录和事件的 error(下面的结算错误形状)并拒绝等待的结算观察者(init().read()、SDK 的 wait())。恢复在输入应用后重新尝试了被中断的提交,直到 durability.maxAttempts 耗尽且没有完成的响应;参见持久性指南了解尝试和超时模型。当终端化结算了其结果无法确认的工具调用时,meta.interruptedTools 将它们列为 { name, id } 对;每个在对话中都有明确的中断错误结果,从未被假定为完成或重试。meta 还携带 attemptCount 和 maxAttempts。
SubmissionTimeoutError
class SubmissionTimeoutError extends FlueError // type: 'submission_timeout'
持久提交结算的终端错误:它成为 submission_settled 记录和事件的 error(下面的结算错误形状)并拒绝等待的结算观察者(init().read()、SDK 的 wait())。提交超过了 durability.timeoutMs;参见持久性指南了解尝试和超时模型。
ToolInputValidationError
class ToolInputValidationError extends FlueError // type: 'tool_input_validation'
模型提供的参数未通过工具的 input 模式。在模型轮次期间,它成为交付回模型的错误工具结果——提交继续,消息面向模型,模型可能更正参数并再次调用;在模型轮次之外,错误传播到调用者。meta 携带 tool 和 issues。
ToolNameConflictError
class ToolNameConflictError extends FlueError // type: 'tool_name_conflict'
工具列表包含重复名称,或自定义或适配器工具使用了框架保留的名称。在会话组装工具时抛出,在任何模型调用之前。参见工具指南了解编写表面。
ToolOutputSerializationError
class ToolOutputSerializationError extends FlueError // type: 'tool_output_serialization'
工具的返回值不可 JSON 序列化,或工具声明了 output 模式但返回了 undefined。在模型轮次期间,它成为交付回模型的错误工具结果——提交继续;在模型轮次之外,错误传播到调用者。meta 携带 tool;当存在时 cause 携带序列化失败。
ToolOutputValidationError
class ToolOutputValidationError extends FlueError // type: 'tool_output_validation'
工具的返回值未通过其 output 模式。在模型轮次期间,它成为交付回模型的错误工具结果——提交继续;在模型轮次之外,错误传播到调用者。meta 携带 tool 和 issues。
ValidationIssue
interface ValidationIssue {
readonly message: string;
readonly path?: readonly PropertyKey[];
}
type ToolValidationIssue = ValidationIssue;
Standard Schema 问题形状中的一个验证失败;path 段是通向失败值的属性键。由上面的验证错误在 meta.issues 中携带。
结算错误形状
submission_settled 事件、持久结算记录和 submission-settled 对话流块携带结果,对于 failed 和 aborted,携带序列化错误:
{
type: 'submission_settled';
submissionId: string;
outcome: 'completed' | 'failed' | 'aborted';
error?: {
name?: string;
message: string;
type?: string;
details?: string;
dev?: string;
meta?: Record<string, unknown>;
};
}
FlueError 用其 name、message、type、details 和 meta 序列化。任何其他失败原因被编辑为通用 internal_error 条目——非 Flue 错误消息从不到达结算记录或线路。结算错误从不携带堆栈。
WORKERS_AI_OVERFLOW_MARKER 和 RETRYABLE_INTERRUPTION_MARKER
const WORKERS_AI_OVERFLOW_MARKER = '(request_too_large)';
const RETRYABLE_INTERRUPTION_MARKER = '(retryable_interruption)';
在没有类型化错误对象存活的地方使用的消息字符串标记——分类读取持久化的助手错误消息。
WORKERS_AI_OVERFLOW_MARKER— 附加到绑定 413 错误消息;压缩层匹配它以触发上下文溢出恢复(压缩并重试)。RETRYABLE_INTERRUPTION_MARKER— 仅由能证明失败是瞬态中断的抛出站点标记(例如 Workers AI 流在没有错误帧或完成原因的情况下结束);重试分类在回退到消息模式启发式之前匹配它。
暴露 Provider 错误的应用可以匹配或剥离这些标记。它们的字符串值就是契约。
实时观测上的 errorInfo
交付给进程内 observe() 订阅者的 FlueObservation 值在失败活动上携带分类的错误详情。字段的形状(接口本身不导出):
// FlueObservation
errorInfo?: {
type: string;
name?: string;
code?: string;
message?: string;
meta?: Record<string, unknown>;
stack?: string;
};
分类规则,应用于抛出的值:
- 名为
AbortError的DOMException→type: 'AbortError'。 FlueError→type是错误的稳定代码;meta是错误的框架拥有的元数据(例如验证问题),因此观察者获得结构化的失败详情而无需解析消息。- 任何其他对象 →
type是其字符串type,否则code,否则name,否则'_OTHER';当它们是字符串时携带name、code和message。 - 字符串 →
{ type: '_OTHER', message };其他 →{ type: '_OTHER' }。 stack— 抛出站点堆栈,仅当失败是从真实的Error实例实时观察到时存在,从不从任意抛出对象。
errorInfo 出现在失败的 tool 观测、失败的 operation 观测和非完成的 submission_settled 观测上。调用者驱动的 shell() bash 工具的失败仅分类到 type/name/message 子集,没有 meta 或 stack。errorInfo 仅限进程内:operation 和 compaction 事件上的持久化形状的 error 字段序列化为 { name, message }(加上 FlueError 的 type、details、meta),持久化记录从不携带 stack——堆栈暴露文件系统路径和部署布局,因此它们远离任何持久化、重放或通过 HTTP 发送的内容。参见事件参考了解观测类型和可观测性指南了解订阅者设置。
轮次错误规范化
模型调用失败不会抛穿智能体渲染。它们规范化为 turn 事件的 response,当提交无法恢复时,以 OperationFailedError 或持久提交错误结算提交。
// turn event
{
type: 'turn';
turnId: string;
purpose: 'agent' | 'compaction' | 'compaction_prefix';
durationMs: number;
request: ModelRequestInfo;
response: ModelResponse;
isError: boolean;
}
interface ModelResponse {
responseId?: string;
responseModel?: string;
output?: LlmAssistantMessage;
usage?: PromptUsage;
finishReason?: string;
providerFinishReason?: string;
gatewayLogId?: string;
error?: /* 上面的 errorInfo 形状 */;
}
finishReason— 规范化的完成词汇:'stop'、'length'、'toolUse'、'error'或'aborted'。每个 Provider 的原生完成值映射到此集合。providerFinishReason— Provider 规范化前的确切完成值(例如 Workers AItool_calls在规范化toolUse之后)。仅遥测;从不是重放或执行身份的一部分。gatewayLogId— 响应级 Cloudflare AI Gateway 日志关联(cf-aig-log-id),从响应自身的头读取,因此并发请求无法交叉归因。仅遥测。error— 分类的错误,当请求抛出或助手消息携带 Provider 错误消息时存在。裸 Provider 错误字符串分类为type: '_OTHER',文本在message中。isError— 当请求抛出或finishReason为'error'或'aborted'时为 true。
边界
type字符串是稳定的机器契约。message、details和dev说明文可能在版本间变化;不要解析它们。- 没有导出的错误代码枚举或列表;代码在类上和本页上。
- 没有按 Provider 的错误层次结构。Provider 失败规范化为轮次结果,最终为
operation_failed或持久提交错误。唯一的 Provider 特定类是CloudflareAIBindingError。 - 取消从不是
FlueError:中止的操作和调度以名为AbortError的DOMException拒绝。 - 线路从不携带
cause、堆栈或非 Flue 错误消息;三者都留在服务端日志中。 - CLI、配置和构建诊断(
flue命令、flue.config.*验证、Vite 插件)是面向人类的 stderr 说明文,没有稳定的机器可读代码。 - 在编写的
app.ts中的应用拥有的路由和中间件返回它们选择的任何状态和主体;Flue 不对它们强加信封或类别(例如没有unauthorized类型)。