Skip to main content

Common errors and solutions

This guide covers the most common errors encountered during ONLYOFFICE plugin development and their solutions.

Plugin initialization errors

Plugin not appearing in menu

Symptoms: Plugin installed but not visible; no errors in console; config file present.

Wrong
{ "guid": "{12345678-ABCD}" }
{ "name": "My Plugin", "version": "1.0.0", }
{ "variations": [{ "url": "plugin.html" }] }
Correct
{ "guid": "asc.{12345678-1234-1234-1234-123456789ABC}" }
{ "name": "My Plugin", "version": "1.0.0" }
{ "variations": [{ "url": "index.html" }] }

Verification:

cat config.json | python -m json.tool
ls index.html
# Verify GUID format starts with "asc."
# Restart ONLYOFFICE completely

Plugin initializes but shows blank screen

Correct
window.Asc.plugin.init = function(data) {
const element = document.getElementById('output');
if (!element) { console.error('Element not found'); return; }
element.textContent = data || 'No data';
};

API method errors

executeMethod not working

Correct
window.Asc.plugin.executeMethod("GetSelectedText", [], function(text) {
console.log('Selected text:', text);
if (text) { processText(text); } else { showMessage('No text selected'); }
});

callCommand fails silently

Correct
window.Asc.plugin.callCommand(function() {
try {
const doc = Api.GetDocument();
if (!doc) { throw new Error('Document not available'); }
const paragraphs = doc.GetAllParagraphs();
return paragraphs.length;
} catch (error) {
console.error('callCommand error:', error);
return null;
}
}, false);

Variables undefined inside callCommand

callCommand runs in the editor's context, not your plugin's. Local variables are not accessible. Use Asc.scope to pass data across the boundary:

Wrong
var text = document.getElementById("input").value;
window.Asc.plugin.callCommand(function() {
// text is undefined here - different execution context
var oParagraph = Api.CreateParagraph();
oParagraph.AddText(text);
Api.GetDocument().InsertContent([oParagraph]);
});
Correct
Asc.scope.text = document.getElementById("input").value;
window.Asc.plugin.callCommand(function() {
var oParagraph = Api.CreateParagraph();
oParagraph.AddText(Asc.scope.text);
Api.GetDocument().InsertContent([oParagraph]);
});

See Passing data into callCommand for details.

Configuration errors

Icons not displaying

Correct
{ "variations": [{ "icons": "resources/%theme-type%(light|dark)/icon%scale%(default).%extension%(png)" }] }

File structure:

my-plugin/
├── config.json
├── index.html
└── resources/
├── light/
│ └── icon.png
└── dark/
└── icon.png

Modal/panel configuration issues

Correct

For modal dialog:

{ "type": "window", "buttons": [{"text": "OK", "primary": true}, {"text": "Cancel"}] }

For side panel:

{ "type": "panel" }

Event handling errors

Events not firing

Correct
window.Asc.plugin.attachEditorEvent("onDocumentContentReady", function() {
console.log('Document ready');
loadInitialData();
});

For selection-aware plugins, set "initOnSelectionChanged": true in config.json - the init function then receives the selected data on every selection change instead of only on plugin open.

Button handler not responding

Correct
window.Asc.plugin.button = function(id) {
if (id === 0) { handleOK(); }
else if (id === 1) { handleCancel(); }
else if (id === -1) { window.Asc.plugin.executeCommand("close", ""); }
};

Data handling errors

JSON parse errors

Correct
fetch('/api/data')
.then(response => {
if (!response.ok) { throw new Error(`HTTP ${response.status}`); }
return response.text();
})
.then(text => {
try {
const data = JSON.parse(text);
processData(data);
} catch (error) {
console.error('Invalid JSON:', text);
showError('Server returned invalid data');
}
})
.catch(error => {
console.error('Fetch error:', error);
showError('Failed to load data');
});

LocalStorage quota exceeded

Correct
function safeSave(key, data) {
try {
const serialized = JSON.stringify(data);
const sizeMB = new Blob([serialized]).size / (1024 * 1024);
if (sizeMB > 5) { console.warn(`Data too large: ${sizeMB.toFixed(2)}MB`); return false; }
localStorage.setItem(key, serialized);
return true;
} catch (error) {
if (error.name === 'QuotaExceededError') {
console.error('Storage quota exceeded');
clearOldData();
}
return false;
}
}

Network errors

CORS errors

Error in console:

Access to fetch at 'https://api.example.com/data' from origin 'http://localhost:3000' has been blocked by CORS policy
Correct
// Route requests through your own backend proxy
fetch('/api/proxy?url=' + encodeURIComponent('https://external-api.com/data'))
.then(response => response.json());
// Server must include: Access-Control-Allow-Origin: *

Timeout errors

Correct
async function fetchWithTimeout(url, timeout = 5000) {
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), timeout);
try {
const response = await fetch(url, { signal: controller.signal });
clearTimeout(timeoutId);
return await response.json();
} catch (error) {
if (error.name === 'AbortError') { throw new Error('Request timeout'); }
throw error;
}
}

UI/UX errors

Elements not found

Correct
window.Asc.plugin.init = function() {
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', setupUI);
} else {
setupUI();
}
};
function setupUI() {
const btn = document.getElementById('myButton');
if (btn) { btn.addEventListener('click', handleClick); }
else { console.error('Button not found in DOM'); }
}