{"record":{"id":"89952dc07dfb270c","repo":"open-webui/open-webui","slug":"no-png-text-chunk-named-textchunkkeyword-foun","errorCode":null,"errorMessage":"No PNG text chunk named \"${textChunkKeyword}\" found","messagePattern":"No PNG text chunk named \"(.+?)\" found","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"src/lib/utils/characters/index.ts","lineNumber":54,"sourceCode":"\t\tfile,\n\t\tjson,\n\t\timage,\n\t\tformats: detectFormats(json),\n\t\tcharacter\n\t};\n};\n\nconst parsePngText = (arrayBuffer) => {\n\tconst textChunkKeyword = 'chara';\n\tconst chunks = readPngChunks(new Uint8Array(arrayBuffer));\n\n\tconst textChunk = chunks\n\t\t.filter((chunk) => chunk.type === 'tEXt')\n\t\t.map((chunk) => decodeTextChunk(chunk.data))\n\t\t.find((entry) => entry.keyword === textChunkKeyword);\n\n\tif (!textChunk) {\n\t\tthrow new Error(`No PNG text chunk named \"${textChunkKeyword}\" found`);\n\t}\n\n\ttry {\n\t\treturn new TextDecoder().decode(Uint8Array.from(atob(textChunk.text), (c) => c.charCodeAt(0)));\n\t} catch (e) {\n\t\tthrow new Error('Unable to parse \"chara\" field as base64', e);\n\t}\n};\n\nconst readPngChunks = (data) => {\n\tconst isValidPng =\n\t\tdata[0] === 0x89 &&\n\t\tdata[1] === 0x50 &&\n\t\tdata[2] === 0x4e &&\n\t\tdata[3] === 0x47 &&\n\t\tdata[4] === 0x0d &&\n\t\tdata[5] === 0x0a &&\n\t\tdata[6] === 0x1a &&","sourceCodeStart":36,"sourceCodeEnd":72,"githubUrl":"https://github.com/open-webui/open-webui/blob/01f4282f1ffe0d6212f58d3afbeae21fffd0c4be/src/lib/utils/characters/index.ts#L36-L72","documentation":"Thrown by POST /api/v1/knowledge/{id}/file/remove when the file exists in the Files table but Knowledges.has_file reports no (knowledge_id, file_id) link — i.e. the file was never added to this knowledge base, or was already removed. This is the 'file does not belong to this knowledge base' guard and returns 400 with NOT_FOUND.","triggerScenarios":"Calling remove with a valid global file_id that belongs to a different knowledge base or to no knowledge base at all; double-submitting the same remove request.","commonSituations":"Same file added to multiple knowledge bases and the client removes it from the wrong one; idempotent retry after the first remove already succeeded; UI state out of sync with the join table.","solutions":["Treat this error as success for idempotent remove flows — the end state (file not in KB) is already achieved.","Confirm the target knowledge id matches the knowledge base the file actually belongs to.","Refresh the file list for the knowledge base before offering a remove action."],"exampleFix":"// before\ntry { await removeFile(kbId, { file_id }); } catch { throw; }\n\n// after\ntry { await removeFile(kbId, { file_id }); }\ncatch (e) { if (!/could not find/.test(e.detail)) throw e; /* already removed */ }","handlingStrategy":"try-catch","validationCode":"const kb = await getKnowledge(id);\nconst isMember = kb.files.some(f => f.id === form.file_id);\nif (!isMember) return; // nothing to remove — already absent","typeGuard":null,"tryCatchPattern":"try { await removeFileFromKnowledge(id, form); }\ncatch (e) { if (e.status === 400 && /could not find/.test(e.detail)) return; /* idempotent success */ throw e; }","preventionTips":["Make remove flows idempotent in the client","Disable the remove button once clicked","Guard concurrent removes with per-file in-flight state"],"tags":["open-webui","knowledge-api","not-found","idempotency"],"backgroundTag":null,"analyzedSha":"01f4282f1ffe0d6212f58d3afbeae21fffd0c4be","analyzedAt":"2026-08-14T18:25:22.715Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}