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'); }
}