Skip to main content

Client-side validation

The SDK validates every request body before it leaves your server. This catches parameter errors instantly with clear messages — no round-trip to the API required.

Validation is enabled by default and covers all POST requests (model submissions, CAD operations, file uploads, etc.).

How it works

When you call any SDK method that sends a request body, the SDK:

  1. Looks up the JSON Schema for the target endpoint
  2. Validates your data against it using a lightweight, eval-free validator
  3. Throws BitbybitValidationError immediately if invalid — the request never reaches the network
  4. Sends the request normally if valid

This works in all runtimes: Node.js, Cloudflare Workers, Deno, Bun.

Why it matters

Although the API server always validates incoming requests, invalid requests that reach the server may still consume compute resources — and those resources can count toward your usage. Client-side validation prevents bad requests from hitting the server at all, which means:

  • Cost savings — no compute time wasted on requests that would be rejected anyway
  • Faster feedback — validation errors appear in microseconds, not after a network round-trip
  • Better developer experience — error messages reference your local data (e.g. #/params/height must be <= 50) instead of a generic server response

Catching validation errors

import { BitbybitClient, BitbybitValidationError } from "@bitbybit-dev/cad-cloud-sdk";

const client = new BitbybitClient({ apiKey: process.env.BITBYBIT_API_KEY! });

try {
await client.models.run("dragon-cup", {
params: { height: 999, radiusBottom: -5 }, // both out of range
outputs: { formats: ["gltf"] },
});
} catch (err) {
if (err instanceof BitbybitValidationError) {
console.error(err.message);
// "Validation failed for DragonCupBody: #/params/height must be <= 50; ..."

console.error(err.errors);
// Array of detailed error objects:
// [{ keyword: "maximum", instanceLocation: "#/params/height", error: "must be <= 50" }, ...]
}
}

Error structure

PropertyTypeDescription
err.messagestringHuman-readable summary of all violations
err.errorsOutputUnit[]Array of individual constraint violations
err.errors[].keywordstringJSON Schema keyword that failed (required, maximum, type, etc.)
err.errors[].instanceLocationstringJSON Pointer to the offending value (e.g. #/params/height)
err.errors[].errorstringDescription of the violation

What gets validated

All constraints from the OpenAPI spec are enforced client-side:

ConstraintExample
requiredMissing operation field in execute body
typePassing a string where a number is expected
minimum / maximumDragon Cup height must be 1–50
minLength / maxLengthFile ID must be at least 1 character
minItems / maxItemsBatch must have 1–50 items
patternEnum values must match allowed patterns
enumOutput format must be one of gltf, step, brep
additionalPropertiesRejects unknown/misspelled fields

Per-model schemas

Each registered model has its own schema with parameter-specific constraints. For example, dragon-cup enforces:

  • height: 1–50
  • radiusBottom: 1–30
  • outputs.formats: at least one format required

Generic schemas

Operations without model-specific schemas still validate against generic schemas:

  • ExecuteBody — requires operation (string)
  • PipelineBody — requires steps (non-empty array)
  • FileUploadBody — requires filename, contentType, bytes
  • BatchModelSubmissionBody — requires items (1–50) and outputs

Disabling validation

Pass validate: false when initializing the client:

const client = new BitbybitClient({
apiKey: process.env.BITBYBIT_API_KEY!,
validate: false,
});

This is useful when:

  • The API has added new endpoints/models that your SDK version doesn't have schemas for yet
  • You want to skip the validation overhead in a hot path (the overhead is minimal — microseconds)
  • You're proxying raw user input and prefer the server's error response format
tip

Even with client-side validation disabled, the API server still validates every request. Client-side validation simply gives you faster, more descriptive error messages during development.

Distinguishing validation errors from API errors

Both error types extend Error, but they are different classes:

import { BitbybitValidationError, BitbybitApiError } from "@bitbybit-dev/cad-cloud-sdk";

try {
await client.cad.execute(body);
} catch (err) {
if (err instanceof BitbybitValidationError) {
// Request never sent — fix the input
console.error("Invalid input:", err.message);
} else if (err instanceof BitbybitApiError) {
// Server returned an error
console.error(`API error ${err.code}:`, err.message);
}
}
BitbybitValidationErrorBitbybitApiError
When thrownBefore request is sentAfter server responds
Network call made?NoYes
Has .errors array?Yes (constraint details)No
Has .statusCode?NoYes (HTTP status)
Has .code?NoYes (e.g. VALIDATION_ERROR, NOT_FOUND)