siyuan-note/siyuan · warning
binary files cannot be edited as text
Error message
binary files cannot be edited as text
What it means
ErrSkillBinary is a sentinel error in the skill file management layer indicating the file content is not editable plain text: it contains a NUL byte or non-whitespace control characters. It is returned by validateManagedSkillSource (on read and write) and by skillSourceReadOnlyReason mapping, so the editor marks the file read-only instead of round-tripping binary data through a text editor.
Solutions
- Do not open or edit this file in the text skill editor — use the file panel to remove/replace it with a text version
- Strip control characters/NUL bytes if the file is genuinely text (e.g. tr -d '\000')
- Move binary assets outside files intended for text editing
Example fix
// before
content contains "\x00" -> util.ErrSkillBinary
// after
sanitized := strings.Map(func(r rune) rune {
if unicode.IsControl(r) && r != '\t' && r != '\n' && r != '\r' && r != '\f' {
return -1
}
return r
}, content)
Defensive patterns
Strategy: type-guard
Validate before calling
function isEditableText(bytes) {
if (bytes.includes(0)) return false;
const s = new TextDecoder('utf-8', {fatal: true}).decode(bytes);
return ![...s].some(c => {
const n = c.codePointAt(0);
return n < 32 && n !== 9 && n !== 10 && n !== 13 && n !== 12;
});
} Try / catch
try {
await api.manageSkillFiles({action: 'read', path});
} catch (e) {
if (e.message.includes('binary files cannot be edited')) {
// surface file as non-editable in UI
}
} Prevention
- Keep binary assets out of text-editable skill files
- Check for NUL bytes before writing via API
- Normalize line endings and strip control chars on import
When it happens
Trigger: Reading or writing a skill file whose content contains \x00 (via strings.ContainsRune) or control runes other than tab/newline/CR/FF; occurs in ManageSkillFiles read/write/create actions.
Common situations: A binary asset (PNG, zip, .so) placed inside a skill directory and opened in the text editor; a script saved with CRLF plus stray control characters; a file corrupted by a bad transfer mode.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- all asset mappings failed
- assetPath is not an image referenced by the document
- assetPath is required for analyze
- at least one asset path or mapping is required
- block [ ] is not a document that can declare a child…
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/0218287c8ab2802b.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/util/skill_manage.go:30
"io/fs"
"os"
"path"
"path/filepath"
"strings"
"sync"
"unicode"
"unicode/utf8"
"github.com/88250/lute/ast"
"github.com/siyuan-note/filelock"
)
const maxManagedSkillSourceSize = 8 * 1024 * 1024
var skillManagementLock sync.Mutex
var (
ErrSkillBinary = errors.New("binary files cannot be edited as text")
ErrSkillEncoding = errors.New("only UTF-8 text files can be edited")
ErrSkillTooLarge = errors.New("text files must be at most 8 MiB")
)
type SkillFileRequest struct {
Action string
Path string
Target string
Content string
Revision string
}
type SkillFileEntry struct {
Path string
IsDir bool
Editable bool
}
View on GitHub (pinned to 9f775e8a12)