Documentation Index

Fetch the complete documentation index at: https://docs.unqork.io/llms.txt

Use this file to discover all available pages before exploring further.

Troubleshooting - BYO

Prev Next

Common issues and solutions for BYO custom component development.

Component Not Rendering

Component Missing from the Module Builder

Symptoms:

  • Custom Component displays an empty drop-down.
  • The component is not listed in the available components.

Solution:

1. Bundle Not Uploaded

# Check if .tar.gz was uploaded
# Go to Admin → Custom Assets
# Verify your component displays in the list

2. Build Failed

# Rebuild
npm run build

# Check for errors in console
# Fix any TypeScript or build errors

3. Wrong Runtime Version

Check package.json byo.runtimeVersion matches your environment:

{
  "byo": {
    "runtimeVersion": "1.0.0"
  }
}

Component Renders as Empty

Symptoms:

  • A component space displays on the canvas.
  • No content visible.
  • No errors in the console.

Solution:

1. Missing Render Logic

// ❌ Bad - no render implementation
export class MyComponent extends HTMLElement {
  connectedCallback() {
    // Nothing here
  }
}

// ✅ Good - implements render
export class MyComponent extends HTMLElement {
  connectedCallback() {
    this.render()
  }
  
  render() {
    this.innerHTML = `<div>Hello</div>`
  }
}

2. Shadow DOM Without Content

// ❌ Bad - shadow DOM but no content
connectedCallback() {
  this.attachShadow({ mode: 'open' })
}

// ✅ Good - shadow DOM with content
connectedCallback() {
  this.attachShadow({ mode: 'open' })
  this.shadowRoot.innerHTML = `<div>Hello</div>`
}

3. Properties Not Set

Check that properties are being set:

set label(value: string) {
  console.log('Label set:', value)  // Debug log
  this._label = value
  this.render()
}

Component Shows Error Message

Symptoms:

  • Error boundary displays "Component failed to load".
  • Browser console displays errors.

Solution: Use the following steps to identify the source of the error.

1. Check browser console

Press F12 and look for:

  • JavaScript errors.
  • Failed network requests.
  • Type errors.

2. Check Network tab

Verify the bundle loaded correctly:

  1. Open the Network tab.
  2. Refresh the page.
  3. Filter by JS.
  4. Check if your bundle displays with status 200.

3. Inspect elements tab

Check if the custom element is defined:

// In browser console
console.log(customElements.get('my-component'))
// Should return constructor, not undefined

4. Test in dev harness

npm run dev

If it works in dev harness but not in Unqork:

  1. Check for platform API incompatibilities.
  2. Verify callbacks are optional chained (?.).
  3. Check for DOM access outside your component.

Properties and State Issues

Properties Not Updating Component

Symptoms:

  • Changing settings in Module Builder has no effect.
  • Component displays stale data.

Solution:

1. Missing Setters

// ❌ Bad - no setter
class MyComponent extends HTMLElement {
  label: string = ''
}

// ✅ Good - implements setter
class MyComponent extends HTMLElement {
  private _label: string = ''
  
  set label(value: string) {
    this._label = value
    this.render()
  }
}

2. Setter Doesn't Trigger Render

set label(value: string) {
  this._label = value
  // ❌ Missing: this.render()
}

// ✅ Good
set label(value: string) {
  this._label = value
  this.render()  // Trigger re-render
}

3. Type Mismatch

set count(value: unknown) {
  // Validate type
  if (typeof value !== 'number') {
    console.warn('count must be number, got:', typeof value, value)
    return
  }
  
  this._count = value
  this.render()
}

debug property values:

set myProp(value: unknown) {
  console.log('myProp set:', value, 'type:', typeof value)
  this._myProp = value
  this.render()
}

Submission Data Not Updating

Symptoms:

  • Calling onSubmissionUpdate has no effect.
  • Other components don't see updated data.

Solution:

1. Callback Not Wired

Check the Module Builder triggers configuration:

{
  "triggers": {
    "onSubmissionUpdate": {
      // Should be configured
    }
  }
}

onSubmissionUpdate doesn't need trigger configuration—it's handled automatically.

2. Calling Incorrectly

// ❌ Bad - calling without optional chaining
this.onSubmissionUpdate(newValue)  // Throws if undefined

// ✅ Good - safe optional chaining
this.onSubmissionUpdate?.(newValue)

3. Passing Undefined

// Check value before updating
if (value !== undefined) {
  this.onSubmissionUpdate?.(value)
}

Debug submission updates:

handleChange(value: string) {
  console.log('Updating submission:', value)
  console.log('Callback exists?', !!this.onSubmissionUpdate)
  this.onSubmissionUpdate?.(value)
}

Event and Callback Issues

Callbacks Not Firing

Symptoms:

  • events don't trigger workflows.
  • Trigger configuration has no effect.

Solution:

1. Missing Optional Chaining

// ❌ Bad - throws if callback undefined
this.onButtonClicked({ label: this._label })

// ✅ Good - safe optional chaining
this.onButtonClicked?.({ label: this._label })

2. Wrong Callback Name

Check that manifest.json and the Module Builder configuration match:

// manifest.json
{
  "events": [
    {
      "type": "buttonClicked"  // Must match property name
    }
  ]
}
// Component
this.onButtonClicked?.({ ... })  // Must be on[EventType]

3. Trigger Not Configured

In Module Builder, verify trigger exists:

{
  "triggers": {
    "onButtonClicked": {
      "contextId": "clickData",
      "targetId": "someLogicComponent"
    }
  }
}

4. Timing Issue

Callbacks are set after connectedCallback. If you call them immediately, they might not exist yet:

// ❌ Bad - callback might not be set yet
connectedCallback() {
  this.onReady?.()  // May be undefined
}

// ✅ Good - wait for platform to wire callbacks
connectedCallback() {
  setTimeout(() => {
    this.onReady?.()
  }, 0)
}

Debug callbacks:

handleClick() {
  console.log('Callbacks available:', {
    onButtonClicked: typeof this.onButtonClicked,
    onSubmissionUpdate: typeof this.onSubmissionUpdate,
  })
  
  this.onButtonClicked?.({ label: this._label })
}

Build and Bundle Issues

Build Fails

Build failures usually trace to one of three issues.

1. TypeScript Errors

error TS2304: Cannot find name 'X'

Solution:

# Install missing types
npm install -D @types/X

# Or fix TypeScript errors in code

2. Module Not Found

Cannot find module './MyComponent'

Solution:

  1. Check that the file exists at the specified path.
  2. Check that the import path is correct.
  3. Check the file extension (.ts vs. .tsx).

3. Syntax Errors

Unexpected token ')'

Solution:

  1. Fix the JavaScript/TypeScript syntax.
  2. Check for missing closing braces, brackets, and parentheses.

Run build with verbose logging:

npm run build -- --mode development

Bundle Too Large

Symptoms:

  • Bundle size > 500KB.
  • Slow page loads.
  • Performance warnings.

Solution:

1. Check bundle size

npm run build
ls -lh dist/*.js

2. Use code splitting

// ❌ Bad - imports everything upfront
import * as d3 from 'd3'

// ✅ Good - lazy load
async loadD3() {
  const d3 = await import('d3')
  return d3
}

3. Import only what you need

// ❌ Bad - imports entire library
import _ from 'lodash'

// ✅ Good - imports specific functions
import debounce from 'lodash/debounce'
import throttle from 'lodash/throttle'

4. Remove unused dependencies

npm uninstall unused-library

5. Analyze bundle

# Add to package.json
"scripts": {
  "analyze": "vite build --mode analyze"
}

Validation Fails

Validation errors occur when the component manifest doesn't match the required schema.

1. Manifest Schema Invalid

manifest.json validation failed

Solution: Check required fields in manifest.json:

{
  "name": "my-component",        // Required
  "main": "my-component.js",     // Required
  "type": "custom",              // Required
  "productType": "BYO",          // Required
  "version": "1.0.0",            // Required
  "runtimeVersion": "1.0.0",     // Required
  "description": "...",          // Required
  "components": []               // Required (can be empty)
}

2. Export Missing

Component 'myButton' export not found in bundle

Solution: Ensure the entry.ts exports match the manifest:

// src/entry.ts
export const myButton = {  // Name must match manifest
  view: async () => MyButton,
  model: async () => MyButtonModel,
}

3. Missing View or Model

Component 'myButton' export is missing 'view' function

Solution: The export must have both view and model:

export const myButton = {
  view: async () => MyButton,      // Required
  model: async () => MyButtonModel, // Required
}

Dev Harness Issues

Dev Harness Shows Blank Page

A blank page in the dev harness typically has one of three causes.

1. Port Already in Use

# Error: Port 5173 already in use

# Use different port
npm run dev -- --port 5001

2. Build Errors

Check terminal for error messages:

# Look for compilation errors
# Fix TypeScript/JavaScript errors

3. Missing Mock Scenarios

Create at least one mock scenario:

// src/MyComponent.mocks.ts
import { defineMockScenario } from '@unqork/byo-sdk/testing'

export const defaultScenario = defineMockScenario({
  name: 'Default',
  props: {
    label: 'Click me',
  },
  callbacks: ['onButtonClicked'],
})

Mock Scenarios Not Displaying

If your scenarios don't display in the drop-down, one of the following issues is usually responsible.

1. File Naming

Scenarios must be in files matching *.mocks.ts:

✓ MyComponent.mocks.ts
✓ scenarios.mocks.ts
✗ MyComponent.scenarios.ts  // Wrong
✗ mocks.ts                  // Wrong

2. Export Format

Export scenario objects:

// ✅ Good
export const myScenario = defineMockScenario({
  name: 'My Scenario',
  props: { ... },
})

// ❌ Bad - not exported
const myScenario = defineMockScenario({ ... })

3. Missing Name

Scenarios need a name to display in the drop-down:

defineMockScenario({
  name: 'Default',  // Required
  props: { ... },
})

Performance Issues

Slow Page Loads

Slow load times with BYO components usually trace to one of four causes.

1. Too Many BYO Components

Each component adds overhead. Combine related components:

❌ 10 small components = 10 bundles to load
✅ 1 combined component = 1 bundle

2. Large Bundle Size

See Bundle Too Large for steps to reduce the bundle size.

3. Synchronous Heavy Operations

Use async with batching:

async processItems(items: Item[]) {
  const batchSize = 100
  for (let i = 0; i < items.length; i += batchSize) {
    const batch = items.slice(i, i + batchSize)
    await processBatch(batch)
    
    // Yield to browser
    await new Promise(resolve => setTimeout(resolve, 0))
  }
}

4. Memory Leaks

Clean up in disconnectedCallback:

private interval: number | null = null

connectedCallback() {
  this.interval = setInterval(this.update, 1000)
}

disconnectedCallback() {
  if (this.interval) {
    clearInterval(this.interval)
  }
}

Browser Compatibility Issues

Component Works in Chrome but Not Safari

Browser compatibility issues typically come from modern API usage, Shadow DOM differences, or unsupported CSS features.

1. Missing Polyfills

Check if you're using any modern APIs:

  • structuredClone: Use a polyfill or deep clone manually.
  • replaceAll: Use split().join() instead.
  • Optional chaining ?.: Supported in all modern browsers.

2. Shadow DOM Differences

Test Shadow DOM behavior across browsers.

3. CSS Features

Some CSS features have browser-specific support:

  • Container queries.
  • :has() selector.
  • Cascade layers.

4. Test in All Target Browsers

Test in Chrome, Firefox, Safari, and Edge.

Getting Help

Debug Checklist

Before asking for help:

  • Check browser console for errors.
  • Test in dev harness (npm run dev).
  • Check bundle loaded in Network tab.
  • Verify the custom element is defined in the console.
  • Test with simple mock data.
  • Check for TypeScript errors.
  • Review FAQ.

Reporting Issues

When reporting bugs, include:

1. SDK Version:

npx byo version

2. Error Messages:

  • Browser console errors.
  • Build/validation errors.
  • Stack traces.

3. Minimal Reproduction:

  • Simplest code that demonstrates the problem.
  • Steps to reproduce.
  • Expected vs. actual behavior.

4. Environment:

  • Browser and version.
  • operating system.
  • Node version.

Contact your Unqork account team or submit a support request through your organization's support portal.

Additional Resources


Changelog

Date Change
2026-05-01 Initial publication