错误处理

Img2Vid API 使用统一错误响应格式。

错误格式

{
  "error": {
    "code": "invalid_api_key",
    "message": "Invalid or inactive API key.",
    "details": {}
  }
}

只有存在额外结构化信息时才会返回 details

鉴权错误

Code HTTP 含义 处理方式
missing_api_key 401 未提供 API Key。 发送 Authorization: Bearer <key>
invalid_api_key 401 API Key 无效、未激活或已删除。 检查或轮换 Key。
invalid_api_key_owner 401 Key 所属用户不存在。 使用有效账号重新创建 Key。

请求错误

Code HTTP 含义 处理方式
invalid_request_body 400 JSON 请求体无效或字段类型不匹配。 校验请求字段和类型。
unsupported_field 400 传入了嵌套结构或内部字段。 移除 inputoptionsscenesub_mode_id、provider、media type 和内部媒体字段。
missing_file 400 上传请求缺少 file 字段。 添加 file 表单字段。

模型与 mode 错误

Code HTTP 含义 处理方式
model_not_found 404 模型不可用。 使用 /api/v1/media_models 返回的模型 key。
model_not_api_configured 422 模型没有公开 API 配置。 选择其他 API 可用模型。
mode_not_supported 422 当前模型不存在该 mode。 使用 /api/v1/media_modelsoperations[].mode
mode_not_api_configured 422 mode 存在但没有公开 endpoint。 使用列表中的其他 operation。
unsupported_input_for_model 422 输入形态不受支持。 查看该模型 mode 的输入要求。
ambiguous_generation_mode 422 输入同时匹配多个 mode。 显式传入 mode
mode_scene_missing 422 mode 缺少内部场景映射。 联系支持,这是配置问题。

文件错误

Code HTTP 含义 处理方式
unsupported_file_type 415 MIME 类型不是图片、视频或音频。 上传支持的媒体文件。
unsupported_file_format 415 文件格式不被所选 mode 支持。 查看模型参考中的格式限制。
file_too_large 413 文件超出大小限制。 压缩文件或选择限制更宽的 mode。
upload_failed 502 存储上传失败。 重试,持续失败请联系支持。
unsupported_upload_target 422 配置的上传目标不支持。 联系支持,这是配置问题。

SDK 错误处理

SDK 会把非 2xx API 响应转换为各语言原生的异常或错误值。轮询 helper 还可能返回超时、生成失败和生成取消相关错误。

下面的片段假设你已经按快速开始初始化了 SDK client,并引入了对应语言需要的 SDK 类型。

JavaScript / TypeScript

import { BubleAPIError } from '@buble/sdk';

try {
  await buble.generations.retrieve('task_id');
} catch (error) {
  if (error instanceof BubleAPIError) {
    console.error(error.status, error.code, error.message, error.details);
  }
}

Python

from buble_ai import BubleAPIError

try:
    client.generations.retrieve("task_id")
except BubleAPIError as error:
    print(error.status_code, error.code, error.message, error.details)

Go

_, err := client.Generations.Retrieve(ctx, "task_id")
if err != nil {
	var apiErr *buble.APIError
	if errors.As(err, &apiErr) {
		fmt.Println(apiErr.StatusCode, apiErr.Code, apiErr.Message, apiErr.Details)
	}
}

Rust

match client.generations().retrieve("task_id").await {
    Err(buble::Error::Api(error)) => {
        eprintln!("{} {:?} {}", error.status, error.code, error.message);
    }
    other => {
        // Handle success or other SDK error variants.
    }
}

Swift

do {
    _ = try await client.generations.retrieve("task_id")
} catch BubleError.api(let error) {
    print(error.statusCode)
    print(error.code ?? "")
    print(error.message)
}

Dart / Flutter

try {
  await client.generations.retrieve('task_id');
} on BubleApiException catch (error) {
  print(error.statusCode);
  print(error.code);
  print(error.message);
}

Elixir

case Buble.Generations.retrieve(client, "task_id") do
  {:ok, task} ->
    task

  {:error, %Buble.Error{type: :api, status: status, message: message}} ->
    IO.puts("Buble API error #{status}: #{message}")
end

Java

try {
    client.generations().retrieve("task_id");
} catch (BubleApiException error) {
    System.err.println(error.getStatusCode());
    System.err.println(error.getCode());
    System.err.println(error.getMessage());
    System.err.println(error.getDetails());
}

.NET

try
{
    await client.Generations.RetrieveAsync("task_id");
}
catch (BubleApiException error)
{
    Console.Error.WriteLine(error.StatusCode);
    Console.Error.WriteLine(error.Code);
    Console.Error.WriteLine(error.Message);
    Console.Error.WriteLine(error.Details);
}

PHP

use Buble\Exception\ApiException;

try {
    $client->generations()->retrieve('task_id');
} catch (ApiException $error) {
    echo $error->statusCode . PHP_EOL;
    echo $error->apiCode . PHP_EOL;
    echo $error->getMessage() . PHP_EOL;
    print_r($error->details);
}

Ruby

begin
  client.generations.retrieve("task_id")
rescue Buble::APIError => error
  warn error.status
  warn error.code
  warn error.message
  warn error.details
end