Troubleshooting & FAQ
Common issues and their solutions when developing Connected Apps.
SDK Issues#
SDK not loading / FacilioAppSDK is not defined#
Cause: The SDK script tag is missing, has a typo in the URL, or your HTML file is loaded directly from the filesystem instead of a web server.
Fix:
- Ensure the script tag is in your
<head>before any app scripts:
<script type="text/javascript" src="https://static.facilio.com/apps-sdk/latest/facilio_apps_sdk.min.js"></script>- Make sure you're serving the page from a web server (
http://orhttps://), not opening the HTML file directly (file://). - Check the browser console for network errors — the CDN URL must be reachable.
app.loaded event never fires#
Cause: The app is not running inside a Facilio iframe (web) or webview (mobile), or the SDK failed to establish a postMessage connection with the host.
Fix:
- Ensure your app is registered as a Connected App in Facilio and the widget URL matches your server.
- Open your app from within Facilio (not standalone in a browser tab).
- Check that your server's
Content-Security-Policyheaders allow being embedded in an iframe or webview. - Verify there are no JavaScript errors before the
app.on('app.loaded', ...)call.
API calls fail silently#
Cause: You're calling API methods before app.loaded fires.
Fix: Always make API calls inside the app.loaded callback:
created() { window.facilioApp = FacilioAppSDK.init();
// WRONG — too early // window.facilioApp.api.fetchAll('workorder', { viewName: 'all' });
window.facilioApp.on('app.loaded', async () => { // CORRECT — SDK is ready const { list } = await window.facilioApp.api.fetchAll('workorder', { viewName: 'all' }); this.workorders = list; });}Widget Issues#
Widget shows a blank white page#
Cause: Your app's URL is unreachable from the browser, the page has a JavaScript error, or CORS/CSP headers are blocking the iframe or webview.
Fix:
- Open the widget URL directly in a browser tab to verify it loads.
- Check the browser console (F12) for errors.
- Ensure your web server allows iframe or webview embedding (no
X-Frame-Options: DENYor restrictiveContent-Security-Policy).
Form field events not firing (form.{field}.changed)#
Cause: The field name in your event listener doesn't match the field's link name in Facilio, or the widget is not configured as a Form widget type.
Fix:
- Verify the field link name in Facilio (Setup → Modules → Fields). Use the link name, not the display name.
- Ensure your widget is configured as
Form - SidebarorForm - Background, not a different widget type. - Test with
form.changedfirst to confirm events are firing at all:
window.facilioApp.on('form.changed', (formData) => { console.log('Form changed:', formData);});Custom Button dialog is too small or too large#
Cause: The dialog defaults to a standard size. You need to explicitly resize it.
Fix: Trigger a resize in the app.loaded callback (web only; use preset size: XS, S, M, L, XL):
window.facilioApp.on('app.loaded', () => { window.facilioApp.interface.trigger('resize', { size: 'L' });});Topbar unseen count not showing#
Cause: The setUnseenCount trigger expects a number (or falsy to clear).
Fix: Pass the count directly:
window.facilioApp.interface.trigger('setUnseenCount', 5);// To clear: window.facilioApp.interface.trigger('setUnseenCount', 0);Data Issues#
fetchAll returns empty list but records exist#
Cause: The viewName doesn't match an existing view, the user lacks permissions, or filters are too restrictive.
Fix:
- Use
viewName: 'all'to start with the broadest view. - Check that the logged-in user has read permission on the module.
- Remove filters temporarily to confirm data is accessible:
const { list, error } = await app.api.fetchAll('workorder', { viewName: 'all'});console.log('Records:', list?.length, 'Error:', error);createRecord / updateRecord fails#
Cause: Required fields are missing, field names don't match the module schema, or the user lacks write permission.
Fix:
- Check the
errorobject in the response for a specific message. - Verify field names match the module's link names (not display names).
- Include all required fields in the data object.
try { await window.facilioApp.api.createRecord('workorder', { data: { subject: 'Test', siteId: 123 } });} catch (error) { console.error('Create failed:', error);}Variables not persisting#
Cause: app.variables.set() returns a Promise — if you don't await it, the value may not be saved before you try to read it.
Fix: Always await or chain .then():
await window.facilioApp.variables.set('myKey', 'myValue');const value = await window.facilioApp.variables.get('myKey');Connector & External API Issues#
invokeConnectorAPI fails with authentication errors#
Cause: The OAuth connector is not configured or the token has expired.
Fix:
- Verify the connector is configured in your Connected App settings (Setup → Connected Apps → Connectors).
- Ensure the connector namespace matches exactly.
- Re-authenticate the connector if the token has expired.
invokeExternalAPI fails with CORS errors#
Cause: External APIs may not allow cross-origin requests from the Facilio domain.
Fix: The SDK proxies external API calls through Facilio's servers, which should avoid CORS issues. If you're still seeing errors:
- Make sure you're using
window.facilioApp.request.invokeExternalAPI()and notfetch()directly. - Check that the external API endpoint is correct and reachable.
FAQ#
Can I use React / Vue / Angular / Svelte?#
Yes. Connected Apps run in an iframe (web) or webview (mobile) and support any web technology. Use whatever framework you prefer — just include the Facilio Apps SDK script tag alongside your framework.
Can I use npm packages?#
Yes. Use any build tool (Webpack, Vite, Rollup) to bundle your app. The only requirement is that the final output includes the SDK script tag and is served from a web server.
Do I need to handle authentication?#
No. The SDK handles authentication automatically when your app runs inside the Facilio iframe or webview. You don't need API keys, tokens, or login flows for Facilio API access.
Can multiple widgets share data?#
Widgets within the same Connected App can share data through the Variables API (app.variables.set/get). Each variable is scoped to the Connected App.
What's the difference between invokeFacilioAPI and api.fetchAll?#
app.api.* methods (fetchAll, createRecord, etc.) are the recommended way to work with Facilio module data. They handle API URLs automatically and are simpler to use. app.request.invokeFacilioAPI() is deprecated — it was a low-level method for calling Facilio REST endpoints directly. Use app.api.* methods for all module data operations.
How do I debug my app?#
- Open browser DevTools (F12) while your app is loaded in Facilio.
- Find your app's iframe or webview in the Elements panel and switch to its JavaScript context in the Console.
- Use
console.log()to trace SDK calls and responses. - Check the Network tab for failed API requests.
Can I export my widget as PDF or image?#
Yes, but through Facilio Script (server-side), not from the widget itself. See the Exporting Widgets guide.