Skip to main content
Version: Next

Status Message Customization

Blueprints can customize the status messages displayed to users in the Sofie UI. This allows you to replace technical status messages with human-friendly ones that are relevant to your broadcast environment.

Overview

Sofie displays error notifications from several sources:

  • Device statuses - from TSR devices (ATEM, CasparCG, vMix, etc.) - customized via Studio Blueprint
  • Package errors - from the Package Manager (media files, thumbnails) - customized via ShowStyle Blueprint
  • System errors - from Sofie Core itself - customized via System Blueprint

Each error type is customized in a different blueprint type, matching where the errors originate.

Device Status Messages (Studio Blueprint)

Device status messages come from TSR (Timeline State Resolver) integrations. Customize them in your Studio Blueprint:

import { StudioBlueprintManifest } from '@sofie-automation/blueprints-integration'
import { AtemStatusCode, CasparCGStatusCode } from 'timeline-state-resolver-types'

export const manifest: StudioBlueprintManifest = {
// ... other manifest properties ...

deviceStatusMessages: {
// Simple string template with placeholders
[AtemStatusCode.DISCONNECTED]: 'Vision mixer offline - check network to {{host}}',

// Use {{deviceName}} for the configured device name
[CasparCGStatusCode.DISCONNECTED]: '{{deviceName}}: Graphics server offline ({{host}}:{{port}})',

// Empty string suppresses the error entirely
[AtemStatusCode.SOME_NOISY_WARNING]: '',
},
}

Using Placeholders

Error messages support {{placeholder}} syntax for dynamic values. Common placeholders include:

  • {{deviceName}} - The configured name of the device in Sofie
  • {{deviceId}} - The internal device ID
  • Additional context from the specific error (e.g., {{host}}, {{port}}, {{channel}})

Function-Based Messages

For complex logic, use a function instead of a string. Functions can return:

  • A string - Use this as the custom message
  • undefined - Fall back to the default TSR message
  • '' (empty string) - Suppress the message entirely
import { DeviceStatusContext } from '@sofie-automation/blueprints-integration'

deviceStatusMessages: {
[CasparCGStatusCode.CHANNEL_ERROR]: (context: DeviceStatusContext) => {
const channel = context.channel as number
if (channel === 1) return 'Primary graphics output failed!'
if (channel === 2) return 'Secondary graphics output failed!'
return `Graphics channel ${channel} error on ${context.deviceName}`
},

// Return undefined to use the default TSR message
[SomeErrorCode.COMPLEX_ERROR]: (context) => {
if (context.isExpected) return undefined // Fall back to default
return `Unexpected error on ${context.deviceName}`
},

// Return empty string to suppress
[SomeErrorCode.NOISY_WARNING]: (context) => {
if (context.severity === 'low') return '' // Suppress low severity
return `Warning on ${context.deviceName}`
},
}

Available Status Codes

Import error codes from timeline-state-resolver-types for type safety:

import {
AtemStatusCode,
CasparCGStatusCode,
VmixStatusCode,
OBSStatusCode,
// ... other device status codes
} from 'timeline-state-resolver-types'

Each device type exports its own error codes. Check the TSR documentation or source code for the complete list.

Package Status Messages (ShowStyle Blueprint)

Package Manager messages are customized in your ShowStyle Blueprint:

import { ShowStyleBlueprintManifest, PackageStatusMessage } from '@sofie-automation/blueprints-integration'

export const manifest: ShowStyleBlueprintManifest = {
// ... other manifest properties ...

packageStatusMessages: {
[PackageStatusMessage.MISSING_FILE_PATH]: 'Media file path not configured - check ingest settings',
[PackageStatusMessage.SCAN_FAILED]: 'Could not scan media file - check file permissions',
[PackageStatusMessage.FILE_NOT_FOUND]: '', // Suppress this message
},
}

System Error Messages (System Blueprint)

System-level errors from Sofie Core are customized in your System Blueprint:

import { SystemBlueprintManifest, SystemErrorCode } from '@sofie-automation/blueprints-integration'

export const manifest: SystemBlueprintManifest = {
// ... other manifest properties ...

systemErrorMessages: {
[SystemErrorCode.DATABASE_CONNECTION_LOST]: 'Database offline - contact IT support',
[SystemErrorCode.SERVICE_UNAVAILABLE]: 'Service {{serviceName}} is not responding',
},
}

Message Resolution

When an error occurs, Sofie resolves the message as follows:

  1. Check blueprint customization - Look for matching error code in the appropriate blueprint
  2. If function - Call it with the error context:
    • Returns undefined → Use default TSR message
    • Returns '' (empty string) → Suppress the message
    • Returns a string → Use that as the message
  3. If string - Interpolate placeholders with context values
  4. If empty string '' - Suppress the message entirely
  5. If not found - Use the default message from TSR/Sofie

Device status resolution happens server-side when the status is received, ensuring consistent messages across all connected clients.

Complete Example

Here's a complete Studio Blueprint example:

import {
StudioBlueprintManifest,
DeviceStatusContext,
} from '@sofie-automation/blueprints-integration'
import { AtemStatusCode, CasparCGStatusCode } from 'timeline-state-resolver-types'

export const deviceStatusMessages: StudioBlueprintManifest['deviceStatusMessages'] = {
// Simple string with placeholders
[AtemStatusCode.DISCONNECTED]: '🎬 Vision mixer offline - check ATEM at {{host}}',
[AtemStatusCode.PSU_FAULT]: '⚠️ ATEM PSU {{psuNumber}} fault - check hardware',

// Graphics server with host:port
[CasparCGStatusCode.DISCONNECTED]: '{{deviceName}}: Graphics offline ({{host}}:{{port}})',

// Function for complex logic
[CasparCGStatusCode.CHANNEL_ERROR]: (context: DeviceStatusContext) => {
const channel = context.channel as number
const channelNames: Record<number, string> = {
1: 'Program graphics',
2: 'Preview graphics',
3: 'DSK graphics',
}
const name = channelNames[channel] || `Channel ${channel}`
return `${name} failed on ${context.deviceName}`
},
}

export const manifest: StudioBlueprintManifest = {
blueprintType: 'studio',
// ... other required properties ...
deviceStatusMessages,
}

Tips

  • Keep messages actionable - Tell users what to do, not just what's wrong
  • Use emoji sparingly - They can help draw attention to critical errors
  • Test with real devices - Disconnect devices to verify your messages appear correctly
  • Check TSR source - Device status codes and their context values are defined in TSR integrations
  • Use functions for complex cases - Conditional logic, pluralization, severity-based filtering

See Also