All validation functions in @svta/cml-c2pa return structured results with an isValid boolean and an errorCodes array. This guide explains the results, the error codes, and the manifest data.
Every result follows the same pattern:
if (!result.isValid) {
for (const code of result.errorCodes) {
console.error(`Validation failure: ${code}`)
}
}
The errorCodes array may contain several codes when several checks fail. When isValid is true, the array is empty.
The LiveVideoStatusCode constants are the live video validation failures that C2PA specification section 19.7 defines.
import { LiveVideoStatusCode } from '@svta/cml-c2pa'
| Constant | Value | Meaning |
|---|---|---|
INIT_INVALID |
livevideo.init.invalid |
Init segment contains an mdat box or BMFF hash mismatch |
MANIFEST_INVALID |
livevideo.manifest.invalid |
C2PA Manifest Box failed standard validation |
SEGMENT_INVALID |
livevideo.segment.invalid |
Crypto failure (signature, hash, or key mismatch), a broken c2pa.manifestId chain, or a failed custom continuity validator |
ASSERTION_INVALID |
livevideo.assertion.invalid |
sequenceNumber or streamId mismatch |
CONTINUITY_METHOD_INVALID |
livevideo.continuityMethod.invalid |
continuityMethod absent, unsupported, or required companion fields missing |
CONTINUITY_METHOD_UNSUPPORTED |
livevideo.continuityMethod.unsupported |
Custom continuity method with no registered validator (always alongside continuityMethod.invalid) |
SESSIONKEY_INVALID |
livevideo.sessionkey.invalid |
Session key invalid or expired |
Example of handling specific error codes:
import { LiveVideoStatusCode } from '@svta/cml-c2pa'
for (const code of result.errorCodes) {
switch (code) {
case LiveVideoStatusCode.SEGMENT_INVALID:
// Cryptographic check failed (signature, hash, or key)
break
case LiveVideoStatusCode.SESSIONKEY_INVALID:
// Session key expired, may need a fresh init segment
break
case LiveVideoStatusCode.ASSERTION_INVALID:
// Sequence number or stream ID problem
break
case LiveVideoStatusCode.CONTINUITY_METHOD_INVALID:
// Manifest ID chain is broken
break
case LiveVideoStatusCode.INIT_INVALID:
// Init segment structure is invalid
break
case LiveVideoStatusCode.MANIFEST_INVALID:
// Embedded manifest failed validation
break
}
}
The C2paStatusCode constants represent manifest integrity failures defined in C2PA specification sections 15 and 18.
import { C2paStatusCode } from '@svta/cml-c2pa'
| Constant | Value | Meaning |
|---|---|---|
ASSERTION_HASHEDURI_MISMATCH |
assertion.hashedURI.mismatch |
Assertion hash does not match the claim reference |
ASSERTION_MISSING |
assertion.missing |
Referenced assertion not found in the assertion store |
ASSERTION_ACTION_INGREDIENT_MISMATCH |
assertion.action.ingredientMismatch |
Action requires an ingredient reference but none is present |
CLAIM_SIGNATURE_MISMATCH |
claim.signature.mismatch |
Claim signature verification failed |
ASSERTION_BMFFHASH_MALFORMED |
assertion.bmffHash.malformed |
BMFF hash assertion or Merkle structure is malformed |
ASSERTION_BMFFHASH_MISMATCH |
assertion.bmffHash.mismatch |
BMFF content hash does not match the committed value |
C2paStatusCode values appear in InitSegmentValidation.errorCodes and ManifestBoxValidationResult.errorCodes, which check manifest integrity. They do not appear in SegmentValidationResult.errorCodes: the VSI/EMSG segment validation (Verifiable Segment Info, in event message boxes) uses only LiveVideoStatusCode.
For VOD Merkle streams, InitSegmentValidation extracts merkleMaps from the c2pa.hash.bmff.v3 assertion and validates the initHash binding of each entry. LiveVideoStatusCode.SESSIONKEY_INVALID is not reported when merkleMaps is not empty, because VOD Merkle segments do not use session keys.
The C2paManifest type represents a parsed C2PA manifest. It is available through InitSegmentValidation.manifest (VSI method) and ManifestBoxValidationResult.manifest (Manifest Box method).
| Field | Type | Description |
|---|---|---|
label |
string |
Manifest label (identifier within the manifest store) |
instanceId |
string | null |
Unique instance ID |
claimGenerator |
string | null |
Tool that generated the claim |
signatureInfo |
C2paSignatureInfo |
Signature metadata |
assertions |
readonly C2paAssertion[] |
All assertions in the manifest |
The signatureInfo object contains:
| Field | Type | Description |
|---|---|---|
issuer |
string | null |
Certificate issuer (Common Name or Organization) |
certNotBefore |
string | null |
Certificate validity start (ISO 8601) |
const { manifest } = init // or result.manifest for the Manifest Box method
if (manifest) {
console.log('Label:', manifest.label)
console.log('Instance ID:', manifest.instanceId)
console.log('Claim generator:', manifest.claimGenerator)
console.log('Issuer:', manifest.signatureInfo.issuer)
console.log('Cert not before:', manifest.signatureInfo.certNotBefore)
for (const assertion of manifest.assertions) {
console.log(`Assertion [${assertion.label}]:`, assertion.data)
}
}
With the VSI/EMSG method, each SegmentValidationResult includes a sequenceResult field: a discriminated union on reason with SequenceValidationReason constants:
import { SequenceValidationReason } from '@svta/cml-c2pa'
| Constant | Value | Valid | Additional Fields | Description |
|---|---|---|---|---|
VALID |
valid |
true |
none | Sequence number is the next expected value |
DUPLICATE |
duplicate |
false |
none | Sequence number was already seen |
GAP_DETECTED |
gap_detected |
false |
missingFrom, missingTo |
One or more sequence numbers were skipped |
OUT_OF_ORDER |
out_of_order |
false |
none | Sequence number is less than the last seen |
SEQUENCE_NUMBER_BELOW_MINIMUM |
sequence_number_below_minimum |
false |
none | Below the session key's minSequenceNumber |
Narrow the type to access the GAP_DETECTED fields:
import { SequenceValidationReason } from '@svta/cml-c2pa'
if (result.sequenceResult.reason === SequenceValidationReason.GAP_DETECTED) {
console.warn(
`Missing segments ${result.sequenceResult.missingFrom}` +
` through ${result.sequenceResult.missingTo}`,
)
}
The two validation methods serve different use cases:
| Aspect | VSI/EMSG (section 19.4) | Manifest Box (section 19.3) |
|---|---|---|
| Init segment required | Yes | No |
| Per-segment overhead | Low (EMSG box only) | High (full manifest per segment) |
| Session keys | Yes | No |
| Manifest access | Init segment only | Every segment |
| Continuity mechanism | Sequence numbers | Manifest ID chaining |
| Functions | validateC2paInitSegment + validateC2paSegment |
validateC2paManifestBoxSegment |
The VSI/EMSG method suits low-overhead real-time streaming where bandwidth matters. The Manifest Box method gives self-contained segments that are verifiable without earlier context.