{"record":{"id":"cde7422f561f95fb","repo":"chenhg5/cc-connect","slug":"expected-number-got-t","errorCode":null,"errorMessage":"expected number, got %T","messagePattern":"expected number, got %T","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"platform/feishu/feishu.go","lineNumber":286,"sourceCode":"\tswitch x := v.(type) {\n\tcase int:\n\t\treturn int64(x), nil\n\tcase int32:\n\t\treturn int64(x), nil\n\tcase int64:\n\t\treturn x, nil\n\tcase uint:\n\t\treturn int64(x), nil\n\tcase uint32:\n\t\treturn int64(x), nil\n\tcase uint64:\n\t\treturn int64(x), nil\n\tcase float32:\n\t\treturn int64(x), nil\n\tcase float64:\n\t\treturn int64(x), nil\n\tdefault:\n\t\treturn 0, fmt.Errorf(\"expected number, got %T\", v)\n\t}\n}\n\n// imageBatchEntry holds image data accumulated for one session while we wait\n// to see if more images are coming. timer is stopped and replaced on every\n// new image to coalesce the window; the pointer is captured by the timer\n// callback so an in-flight (or stale) timer can detect that its entry has\n// been superseded and exit without dispatching.\ntype imageBatchEntry struct {\n\tsessionKey   string\n\tuserID       string\n\tuserName     string\n\tchatName     string\n\trctx         replyContext\n\tquoted       quotedMessage\n\tonAccepted   func()\n\timages       []core.ImageAttachment\n\tmessageIDs   []string","sourceCodeStart":268,"sourceCodeEnd":304,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/platform/feishu/feishu.go#L268-L304","documentation":"Returned by coerceMilliseconds when a config value that must be numeric (e.g. image_batch_window_ms) is not an int/int64/float Go basic type. The %T verb reveals the actual Go type found, typically a string from TOML quoting or a nested map. newPlatform surfaces it wrapped by the invalid image_batch_window_ms/resource_chunk_size_bytes errors.","triggerScenarios":"Setting image_batch_window_ms = \"500\" (string) or a table/bool in config.toml instead of a bare number, then starting the feishu platform.","commonSituations":"TOML quoting mistake: values copied from JSON configs keep quotes; users writing '500ms' as a duration string when only plain integers are accepted.","solutions":["Remove quotes around the numeric value in config.toml (image_batch_window_ms = 500).","Convert duration strings to plain integer milliseconds yourself ('500ms' → 500).","Check the %T in the message to see what type was parsed (e.g. string, bool, map)."],"exampleFix":"// before (config.toml)\nimage_batch_window_ms = \"500\"\n// after\nimage_batch_window_ms = 500","handlingStrategy":"validation","validationCode":"v, ok := opts[\"image_batch_window_ms\"]\nswitch v.(type) {\ncase int, int64, float32, float64:\n    // ok\ndefault:\n    return fmt.Errorf(\"image_batch_window_ms must be a bare number, got %T\", v)\n}","typeGuard":"func isNumber(v any) bool {\n    switch v.(type) {\n    case int, int64, float32, float64:\n        return true\n    }\n    return false\n}","tryCatchPattern":null,"preventionTips":["Never quote numeric options in TOML.","Validate config.toml at startup with a linter or cc-connect config check.","Use plain integer milliseconds, not duration strings."],"tags":["feishu","config","type-mismatch"],"backgroundTag":"config-type-mismatch","analyzedSha":"4000b2338aa6e850c99df54f8b0ed6ed7460b401","analyzedAt":"2026-09-06T11:45:09.575Z","contentChangedAt":"2026-09-06T11:45:09.575Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}