{"record":{"id":"ad8d680c013ed258","repo":"fyne-io/fyne","slug":"string-lengths-over-1-15-not-yet-supported-got-l","errorCode":null,"errorMessage":"string lengths over 1<<15 not yet supported, got len %d","messagePattern":"string lengths over 1<<15 not yet supported, got len (.+?)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/fyne/internal/mobile/binres/pool.go","lineNumber":190,"sourceCode":"}\n\n// MarshalBinary outputs the binary format from a given pool\nfunc (pl *Pool) MarshalBinary() ([]byte, error) {\n\tif pl.IsUTF8() {\n\t\treturn nil, fmt.Errorf(\"encode utf8 not supported\")\n\t}\n\n\tvar (\n\t\thdrlen = 28\n\t\t// indices of string indices\n\t\tiis    = make([]uint32, len(pl.strings))\n\t\tiislen = len(iis) * 4\n\t\t// utf16 encoded strings concatenated together\n\t\tstrs []uint16\n\t)\n\tfor i, x := range pl.strings {\n\t\tif len(x)>>16 > 0 {\n\t\t\tpanic(fmt.Errorf(\"string lengths over 1<<15 not yet supported, got len %d\", len(x)))\n\t\t}\n\t\tp := utf16.Encode([]rune(x))\n\t\tif len(p) == 0 {\n\t\t\tstrs = append(strs, 0x0000, 0x0000)\n\t\t} else {\n\t\t\tstrs = append(strs, uint16(len(p))) // string length (implicitly includes zero terminator to follow)\n\t\t\tstrs = append(strs, p...)\n\t\t\tstrs = append(strs, 0) // zero terminated\n\t\t}\n\t\t// indices start at zero\n\t\tif i+1 != len(iis) {\n\t\t\tiis[i+1] = uint32(len(strs) * 2) // utf16 byte index\n\t\t}\n\t}\n\n\t// check strings is 4-byte aligned, pad with zeros if not.\n\tfor x := (len(strs) * 2) % 4; x != 0; x -= 2 {\n\t\tstrs = append(strs, 0x0000)","sourceCodeStart":172,"sourceCodeEnd":208,"githubUrl":"https://github.com/fyne-io/fyne/blob/8860ee95c356385effa5a7be51adb11c6be9d2b6/cmd/fyne/internal/mobile/binres/pool.go#L172-L208","documentation":"The binary resource string-pool encoder writes every string with a UTF-16 length prefix that must fit in 16 bits. Strings whose Go byte length has bits above bit 15 set (len(x)>>16 > 0) cannot be represented, so the encoder panics citing the 1<<15 supported limit. The pool holds every string compiled into the APK resources - manifest values, string resources, etc.","triggerScenarios":"Any single string at or beyond the length limit while packaging for Android: a giant label/description, a huge deep-link or scheme list in AndroidManifest.xml, or one enormous strings.xml entry.","commonSituations":"Base64 blobs, API keys or certificates pasted into string resources; concatenated locale text generated by scripts; manifests with embedded data payloads.","solutions":["Split the oversized string into multiple shorter resources and join them at runtime","Move the payload out of resources into a bundled asset file loaded with fyne storage or os.ReadFile","Shorten generated manifest fields (descriptions, URI lists) to well below 32Ki characters"],"exampleFix":"<!-- before (strings.xml) -->\n<string name=\"payload\">AAAA...65KB-of-base64...==</string>\n\n<!-- after -->\n<string name=\"payload_1\">first 16Ki chars</string>\n<string name=\"payload_2\">remaining chars</string>","handlingStrategy":"validation","validationCode":"// Pre-flight: flag any resource/manifest string that could blow the UTF-16 length prefix.\nconst maxStringLen = 1 << 15 // conservative: the pool writes a uint16 length\nfunc tooLong(s string) bool { return len([]rune(s)) >= maxStringLen }\n\nfor name, val := range stringResources {\n    if tooLong(val) { return fmt.Errorf(\"resource %s exceeds %d chars; split it or move to an asset\", name, maxStringLen) }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never paste base64 blobs or keys into strings.xml; bundle them as asset files","Add a CI length check on generated resources before 'fyne package'","Split large generated text into chunks under ~16Ki characters each"],"tags":["android","resources","string-pool","packaging","length-limit","go"],"backgroundTag":null,"analyzedSha":"8860ee95c356385effa5a7be51adb11c6be9d2b6","analyzedAt":"2026-08-15T22:01:51.624Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}