louislam/uptime-kuma · warning · Error
Only allowed PNG logo.
Error message
Only allowed PNG logo.
What it means
Thrown by saveStatusPage when imgDataUrl starts with 'data:' but does not start with the PNG data-URL header 'data:image/png;base64,'. Only PNG logos are accepted because the saved file is hard-coded to logo<id>.png via ImageDataURI.outputFile.
Source
Thrown at server/socket-handlers/status-page-socket-handler.js:312
checkLogin(socket);
// Save Config
let statusPage = await R.findOne("status_page", " slug = ? ", [slug]);
if (!statusPage) {
throw new Error("No slug?");
}
checkSlug(config.slug);
const header = "data:image/png;base64,";
// Check logo format
// If is image data url, convert to png file
// Else assume it is a url, nothing to do
if (imgDataUrl.startsWith("data:")) {
if (!imgDataUrl.startsWith(header)) {
throw new Error("Only allowed PNG logo.");
}
const filename = `logo${statusPage.id}.png`;
// Convert to file
await ImageDataURI.outputFile(imgDataUrl, Database.uploadDir + filename);
config.logo = `/upload/${filename}?t=` + Date.now();
} else {
config.logo = imgDataUrl;
}
statusPage.slug = config.slug;
statusPage.title = config.title;
statusPage.description = config.description;
statusPage.icon = config.logo;
((statusPage.autoRefreshInterval = config.autoRefreshInterval), (statusPage.theme = config.theme));
//statusPage.published = ;
//statusPage.search_engine_index = ;View on GitHub (pinned to 6b5ea01557)
Solutions
- Convert the logo to PNG before sending (canvas toBlob('image/png') or an image tool).
- If the image is hosted externally, pass a URL instead of a data: URL (the else branch treats it as a URL).
- Reject non-PNG files in the client file picker before encoding to data URL.
Example fix
// before
socket.emit("saveStatusPage", slug, config, "data:image/jpeg;base64,...", groups, cb);
// after
socket.emit("saveStatusPage", slug, config, "data:image/png;base64,...", groups, cb); Defensive patterns
Strategy: validation
Validate before calling
const PNG_HEADER = "data:image/png;base64,";
function encodeAsPng(file) { /* use canvas.toBlob('image/png') */ }
if (imgDataUrl.startsWith("data:") && !imgDataUrl.startsWith(PNG_HEADER)) {
imgDataUrl = await encodeAsPng(file);
}
socket.emit("saveStatusPage", slug, config, imgDataUrl, groups, cb); Type guard
function isPngDataUrl(s) {
return typeof s === "string" && s.startsWith("data:image/png;base64,");
} Try / catch
try { await emitAsync("saveStatusPage", slug, config, img, groups, cb); }
catch (e) { if (/Only allowed PNG/.test(e.message)) convertAndRetry(); else throw e; } Prevention
- Accept only image/png in the file picker.
- Convert non-PNG images to PNG before encoding.
- Use a URL instead of a data URL for hosted logos.
When it happens
Trigger: Client uploads a JPEG, GIF, SVG, or WebP image as a data URL for the status page logo; the data: prefix is present but the MIME is not image/png.
Common situations: User pastes/uploads a non-PNG logo; frontend does not pre-convert; browser produces image/jpeg for screenshots; SVG rejected for security.
Related errors
- Please input title
- Please input content
- Invalid analytics type
- Please input all fields
- Slug -Accept string only
AI-assisted analysis of louislam/uptime-kuma@6b5ea01557 (2026-08-12).
Data as JSON: /api/errors/5687616419ebfbf3.
Report an issue: GitHub.