Error Handling
Learn how SDK components handle errors gracefully without breaking your application.
Graceful Degradation
All SDK components are designed to fail gracefully and never throw exceptions that would break your application.
Null or Undefined Assets
When no asset is provided, components return null (nothing rendered):
<BynderDamImage asset={null} />
{/* Renders nothing */}
<BynderDamLink asset={undefined}>Click me</BynderDamLink>
{/* Renders nothing */}
<BynderDamVideo asset={null} />
{/* Renders nothing */}Use Case: Safely render components even when data hasn't loaded yet or is missing.
Invalid Asset Structure
When the asset structure is invalid (empty assets array or missing required fields), components render error text that can be styled:
const invalidAsset = {
type: 'Assets',
assets: [], // Empty array
file: null,
overrideAltText: null,
};
<BynderDamImage
asset={invalidAsset}
className="text-red-600 font-bold bg-red-100 px-4 py-2 rounded"
/>
{/* Renders: "Invalid asset data" with custom styling */}Styled Error Messages
Error messages respect the className prop, allowing you to style them consistently with your design system:
<BynderDamVideo
asset={invalidAsset}
className="text-purple-600 italic bg-purple-50 p-3 rounded border border-purple-300"
/>
{/* Renders: "Invalid video data" with custom styling */}Error Messages Reference
| Component | Null/Undefined Behavior | Invalid Data Message |
|---|---|---|
BynderDamImage | Returns null | "Invalid asset data" |
BynderDamNextImage | Returns null | "Invalid asset data" |
BynderDamLink | Returns null | "Invalid asset data" |
BynderDamVideo | Returns null | "Invalid video data" |
Error Handling Patterns
With Loading States
function AssetDisplay({ assetData }) {
const [asset, setAsset] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
if (!assetData) {
setLoading(false);
return;
}
try {
const parsed = JSON.parse(assetData);
setAsset(parsed);
} catch (e) {
setError('Failed to parse asset data');
} finally {
setLoading(false);
}
}, [assetData]);
if (loading) {
return <div className="spinner">Loading...</div>;
}
if (error) {
return <div className="text-red-600">{error}</div>;
}
return (
<BynderDamImage
asset={asset}
alt="Asset"
className="w-full rounded-lg"
/>
);
}With Fallback UI
function SafeImage({ asset, fallback = '/placeholder.jpg' }) {
if (!asset?.assets?.[0]) {
return <img src={fallback} alt="Placeholder" />;
}
return (
<BynderDamImage
asset={asset}
alt="Asset"
onError={(e) => {
e.target.src = fallback;
}}
/>
);
}With Error Boundaries
import { ErrorBoundary } from 'react-error-boundary';
function FallbackComponent({ error }) {
return (
<div className="text-red-600 p-4 border border-red-300 rounded">
<h3>Something went wrong:</h3>
<pre>{error.message}</pre>
</div>
);
}
function App() {
return (
<ErrorBoundary FallbackComponent={FallbackComponent}>
<BynderDamImage asset={asset} alt="Product" />
</ErrorBoundary>
);
}Defensive Data Parsing
function parseAssetSafely(assetData: string) {
if (!assetData || typeof assetData !== 'string') {
return null;
}
try {
const parsed = JSON.parse(assetData);
// Validate structure
if (!parsed?.assets || !Array.isArray(parsed.assets)) {
console.warn('Invalid asset structure:', parsed);
return null;
}
return parsed;
} catch (error) {
console.error('Failed to parse asset data:', error);
return null;
}
}
// Usage
function MyComponent({ assetData }) {
const asset = parseAssetSafely(assetData);
return <BynderDamImage asset={asset} alt="Safe asset" />;
}TypeScript Type Guards
import type { BynderAssetResponse } from '@neworange/bynder-dam-connector-sitecoreai-sdk';
function isValidAsset(asset: unknown): asset is BynderAssetResponse {
if (!asset || typeof asset !== 'object') return false;
const a = asset as BynderAssetResponse;
return (
a.type === 'Assets' &&
Array.isArray(a.assets) &&
a.assets.length > 0
);
}
// Usage
function SafeComponent({ asset }: { asset: unknown }) {
if (!isValidAsset(asset)) {
return <div>Invalid asset data</div>;
}
return <BynderDamImage asset={asset} alt="Valid asset" />;
}Logging and Monitoring
Track Rendering Errors
function MonitoredImage({ asset, alt }) {
const handleError = (error) => {
console.error('Image failed to load:', {
asset: asset?.assets?.[0]?.id,
error: error.message,
});
// Send to monitoring service
analytics.track('image_load_error', {
assetId: asset?.assets?.[0]?.id,
});
};
return (
<BynderDamImage
asset={asset}
alt={alt}
onError={handleError}
/>
);
}Debug Mode
function DebugAssetComponent({ asset, debug = false }) {
if (debug) {
console.log('Asset data:', asset);
console.log('Has assets:', asset?.assets?.length);
console.log('First asset:', asset?.assets?.[0]);
}
return <BynderDamImage asset={asset} alt="Debug asset" />;
}Error Handling Best Practices
✅ Do's
- Always check for null/undefined before rendering
- Use optional chaining when accessing nested properties
- Provide fallback UI for better user experience
- Log errors for debugging and monitoring
- Validate data structure when parsing JSON strings
- Use TypeScript type guards for runtime validation
- Style error messages consistently with your design system
❌ Don'ts
- Don't assume data is always valid - always validate
- Don't throw custom errors - components already handle errors
- Don't ignore console warnings - they indicate data issues
- Don't skip null checks - always handle missing data
- Don't use try-catch around components - they don't throw
Summary
The SDK's error handling approach ensures:
- No exceptions thrown - Components never break your app
- Graceful degradation - Invalid data renders error text, not nothing
- Styleable errors - Error messages can be styled with className
- Consistent behavior - All components handle errors the same way
- Developer-friendly - Clear error messages for debugging
This defensive approach means you can confidently use SDK components knowing they won't cause runtime errors or break your application.