--- title: "Troubleshooting - BYO" slug: "troubleshooting-byo" updated: 2026-10-07T18:51:36Z published: 2026-10-07T18:51:36Z canonical: "docs.unqork.io/troubleshooting-byo" --- > ## 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 Common issues and solutions for BYO custom component development. ## Component Not Rendering ### Component Missing from the Module Builder **Symptoms**: - Custom Component displays an empty selector. - The component is not listed in the available components. **Solution**: **1. Bundle Not Uploaded** ```bash # Check if .tar.gz was uploaded # Go to Admin → Custom Assets # Verify your component displays in the list ``` **2. Build Failed** ```bash # 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. This field is optional and present if added manually — if it is not in your `package.json`, skip this step: ```json {  "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** ```typescript // ❌ 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 = `
Hello
`  } } ``` **2. Shadow DOM Without Content** ```typescript // ❌ Bad - shadow DOM but no content connectedCallback() {  this.attachShadow({ mode: 'open' }) } // ✅ Good - shadow DOM with content connectedCallback() {  this.attachShadow({ mode: 'open' })  this.shadowRoot.innerHTML = `
Hello
` } ``` **3. Properties Not Set** Check that properties are being set: ```typescript 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: ```javascript // In browser console console.log(customElements.get('my-component')) // Should return constructor, not undefined ``` **4. Test in dev harness** ```bash 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** ```typescript // ❌ 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** ```typescript 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** ```typescript 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**: ```typescript 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: ```json {  "triggers": {    "onSubmissionUpdate": {      // Should be configured    }  } } ``` `onSubmissionUpdate` doesn't need configuration. It's handled automatically. **2. Calling Incorrectly** ```typescript // ❌ Bad - calling without optional chaining this.onSubmissionUpdate(newValue)  // Throws if undefined // ✅ Good - safe optional chaining this.onSubmissionUpdate?.(newValue) ``` **3. Passing Undefined** ```typescript // Check value before updating if (value !== undefined) {  this.onSubmissionUpdate?.(value) } ``` **Debug submission updates**: ```typescript 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** ```typescript // ❌ 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: ```json // manifest.json {  "events": [    {      "type": "buttonClicked"  // Must match property name    }  ] } ``` ```typescript // Component this.onButtonClicked?.({ ... })  // Must be on[EventType] ``` **3. Trigger Not Configured** In Module Builder, verify trigger exists: ```json {  "triggers": {    "onButtonClicked": {      "contextId": "clickData",      "targetId": "someLogicComponent"    }  } } ``` **4. Timing Issue** Callbacks are set after `connectedCallback`. If you call them immediately, they might not exist yet: ```typescript // ❌ 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**: ```typescript handleClick() {  console.log('Callbacks available:', {: typeof this.onButtonClicked,: typeof this.onSubmissionUpdate,  })    this.onButtonClicked?.({ label: this._label }) } ``` ## Build and Bundle Issues ### Build Fails Build failures usually trace to of three issues. **1. TypeScript Errors** ```plaintext error TS2304: Cannot find name 'X' ``` **Solution**: ```bash # Install missing types npm install -D @types/X # Or fix TypeScript errors in code ``` **2. Module Not Found** ```plaintext Cannot find module './MyComponent' ``` **Solution**: 1. Check that the file exists at the specified . 2. Check that the import path is correct. 3. Check the file extension (`.ts` vs `.tsx`). **3. Syntax Errors** ```plaintext Unexpected token ')' ``` **Solution**: 1. Fix the JavaScript/TypeScript syntax. 2. Check for missing closing braces, brackets, and parentheses. **Run build with verbose logging**: ```bash npm run build -- --mode development ``` ### Bundle Too Large **Symptoms**: - Bundle size > 500KB. - Slow page loads. - Performance warnings. **Solution**: **1. Check bundle size** ```bash npm run build ls -lh dist/*.js ``` **2. Use code splitting** ```typescript // ❌ Bad - imports everything upfront import * as d3 from 'd3' // ✅ Good - lazy load async loadD3() {  const d3 = await import('d3')  return d3 } ``` **3. Import what you need** ```typescript // ❌ 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** ```bash npm uninstall unused-library ``` **5. Analyze bundle** ```bash # 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** ```plaintext manifest.json validation failed ``` **Solution**: Check required fields in `manifest.json`: ```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": []               // Optional } ``` **2. Export Missing** ```plaintext Component 'myButton' export not found in bundle ``` **Solution**: Ensure the `entry.ts` exports match the manifest: ```typescript // src/entry.ts export const myButton = {  // Name must match manifest  view: async () => MyButton,  model: async () => MyButtonModel, } ``` **3. Missing View or Model** ```plaintext Component 'myButton' export is missing 'view' function ``` **Solution**: The export must have both `view` and `model`: ```typescript 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 of three causes. **1. Port Already in Use** ```bash # Error: Port 5173 already in use # Use different port npm run dev -- --port 5001 ``` **2. Build Errors** Check terminal for error messages: ```bash # Look for compilation errors # Fix TypeScript/JavaScript errors ``` **3. Missing Mock Scenarios** Create at least mock scenario: ```typescript // 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 Appearing If your scenarios don't appear in the selector, of the following issues is usually responsible. **1. File Naming** Scenarios must be in files matching `*.mocks.ts`: ```plaintext ✓ MyComponent.mocks.ts ✓ scenarios.mocks.ts ✗ MyComponent.scenarios.ts  // Wrong ✗ mocks.ts                  // Wrong ``` **2. Export Format** Export scenario objects: ```typescript // ✅ Good export const myScenario = defineMockScenario({  name: 'My Scenario',  props: { ... }, }) // ❌ Bad - not exported const myScenario = defineMockScenario({ ... }) ``` **3. Missing Name** Scenarios need a name to appear in the selector: ```typescript defineMockScenario({  name: 'Default',  // Required  props: { ... }, }) ``` ## Performance Issues ### Slow Page Loads Slow load times with BYO components usually trace to of four causes. **1. Too Many BYO Components** Each component adds overhead. Combine related components: ```plaintext ❌ 10 small components = 10 bundles to load ✅ 1 combined component = 1 bundle ``` **2. Large Bundle Size** See [Bundle Too Large](/unqorkai/docs/troubleshooting-byo#bundle-too-large) for steps to reduce the bundle size. **3. Synchronous Heavy Operations** Use async with batching: ```typescript 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`: ```typescript 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](/unqorkai/docs/faq-byo). ### Reporting Issues When reporting bugs, include: **1. SDK Version**: ```bash 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. --- **Changelog** | Date | Change | | --- | --- | | 2026-10-01 | Converted em dash to period; added blank lines before all lists for correct MDX rendering (EN-8151). | | 2026-05-01 | Initial publication | JavaScript is an object-oriented computer programming language. It is most-commonly used for interactive effects in the browser. APIs (application programming interfaces) are a set of protocols and definitions developers use to build and integrate application software. APIs act as the connective tissue between products and services. The Document Object Model (DOM) is the data representation of objects that form the structure and content of a document on the web. The DOM represents the page. Schema is a declarative language that defines the structure, content, and constraints of the data. An object is a type of data structure that represents a single, self-contained entity that acts as a container for the characteristics of that entity. Cascading Style Sheets (CSS) is a style sheet language used for presenting how a HTML or XML document looks to end-users. APIs (application programming interfaces) are a set of protocols and definitions developers use to build and integrate application software. APIs act as the connective tissue between products and services. A query lets you retrieve, access, manipulate, and delete data in a database. Rendering is the process of loading components and displaying the final result on the front-end screen.