{"record":{"id":"fa12dde68a2cefb6","repo":"lionsoul2014/ip2region","slug":"searchers-must-be-0","errorCode":null,"errorMessage":"searchers must be > 0","messagePattern":"searchers must be > 0","errorType":"validation","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"binding/cangjie/src/service/config.cj","lineNumber":23,"sourceCode":"\n// Cache policy constants - match Searcher modes\npublic let FileOnly: Int64 = 0\npublic let VectorIndex: Int64 = 1\npublic let ContentBuff: Int64 = 2\n\n// Config holds xdb file configuration and pre-loaded data for creating Searcher instances\npublic class Config {\n    public let cachePolicy: Int64\n    public let ipVersion: Version\n    public let xdbPath: String\n    public let header: Header\n    public let vIndex: Array<Byte>\n    public let cBuffer: Array<Byte>\n    public let searchers: Int64\n\n    public init(cachePolicy: Int64, ipVersion: Version, xdbPath: String, searchers: Int64) {\n        if (searchers <= 0) {\n            throw Exception(\"searchers must be > 0\")\n        }\n\n        this.cachePolicy = cachePolicy\n        this.ipVersion = ipVersion\n        this.xdbPath = xdbPath\n        this.searchers = searchers\n\n        let content = File.readFrom(Path(xdbPath))\n        this.header = newHeaderFromBytes(content)\n\n        // Verify IP version matches\n        let detectedVersion = versionFromHeader(this.header)\n        if (detectedVersion.id != ipVersion.id) {\n            throw Exception(\"xdb file IP version mismatch: expected ${ipVersion.name}, got ${detectedVersion.name}\")\n        }\n\n        if (cachePolicy == VectorIndex) {\n            this.vIndex = loadVectorIndex(content)","sourceCodeStart":5,"sourceCodeEnd":41,"githubUrl":"https://github.com/lionsoul2014/ip2region/blob/c1a1fc7d5941760db3f8431dc05c48cf7f0e30a1/binding/cangjie/src/service/config.cj#L5-L41","documentation":"The Cangjie Config constructor validates that the searcher pool size (searchers) is a positive integer. A pool of zero or fewer searchers could never serve a lookup, so construction fails fast with this exception.","triggerScenarios":"Creating Config (or the service built on it) with searchers <= 0 — e.g. reading the pool size from config that defaults to 0, an env var parsed as 0, or an arithmetic result of 0.","commonSituations":"Config file with 'searchers = 0', missing environment variable yielding 0 after toInt64, or computing pool size as cpus - overhead which floors to 0 on small machines.","solutions":["Pass a positive searchers value (e.g. number of worker threads you intend to run)","Clamp the configured value before constructing: max(1, configuredValue)","Fix the config file/env var supplying the pool size","Choose the pool size to match expected concurrency (e.g. CPU core count)"],"exampleFix":"// before\nlet cfg = Config(cachePolicy, ver, xdbPath, envSearchers) // envSearchers = 0\n// after\nlet n = if (envSearchers > 0) { envSearchers } else { 4 }\nlet cfg = Config(cachePolicy, ver, xdbPath, n)","handlingStrategy":"validation","validationCode":"// Cangjie: clamp before constructing Config\nlet n = if (rawSearchers > 0) { rawSearchers } else { 4 }\n// then: Config(cachePolicy, ipVersion, xdbPath, n)","typeGuard":"func poolSizeOk(n: Int64): Bool { return n > 0 }","tryCatchPattern":"try {\n    let cfg = Config(cachePolicy, ver, xdbPath, searchers)\n} catch (e: Exception) {\n    log.error(\"config rejected: ${e.message}\")\n    return InitResult.Failed\n}","preventionTips":["Provide non-zero defaults for pool size config keys","Validate env/config integers after parsing (0 is a common missing-value default)","Size the pool from CPU count with a floor of 1","Fail fast with a clear message when the configured size is <= 0"],"tags":["cangjie","config-validation","pool-size"],"backgroundTag":"invalid-config-value","analyzedSha":"c1a1fc7d5941760db3f8431dc05c48cf7f0e30a1","analyzedAt":"2026-09-02T16:58:39.988Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T21:17:11.164Z"}