{"record":{"id":"220223d058121a88","repo":"crowdsecurity/crowdsec","slug":"unable-to-dump-metas-w","errorCode":null,"errorMessage":"unable to dump metas: %w","messagePattern":"unable to dump metas: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/alertcontext/alertcontext.go","lineNumber":131,"sourceCode":"\t\t\terrors = append(errors, fmt.Errorf(\"error truncating content for %s: %w\", key, err))\n\t\t\tcontinue\n\t\t}\n\n\t\tmeta := models.MetaItems0{\n\t\t\tKey:   key,\n\t\t\tValue: valueStr,\n\t\t}\n\t\tmetas = append(metas, &meta)\n\t}\n\n\treturn metas, errors\n}\n\n// Truncate an individual []string to fit in the context value length\nfunc TruncateContext(values []string, contextValueLen int) (string, error) {\n\tvalueByte, err := json.Marshal(values)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"unable to dump metas: %w\", err)\n\t}\n\n\tret := string(valueByte)\n\tfor len(ret) > contextValueLen {\n\t\t// if there is only 1 value left and that the size is too big, truncate it\n\t\tif len(values) == 1 {\n\t\t\tvalueToTruncate := values[0]\n\t\t\thalf := len(valueToTruncate) / 2\n\t\t\tlastValueTruncated := valueToTruncate[:half] + \"...\"\n\t\t\tvalues = values[:len(values)-1]\n\t\t\tvalues = append(values, lastValueTruncated)\n\t\t} else {\n\t\t\t// if there is multiple value inside, just remove the last one\n\t\t\tvalues = values[:len(values)-1]\n\t\t}\n\n\t\tvalueByte, err = json.Marshal(values)\n\t\tif err != nil {","sourceCodeStart":113,"sourceCodeEnd":149,"githubUrl":"https://github.com/crowdsecurity/crowdsec/blob/909b5157986a2b2c2163300fdaef5ed01289f7d2/pkg/alertcontext/alertcontext.go#L113-L149","documentation":"TruncateContext first JSON-marshals the whole []string value to measure its size against contextValueLen. If that initial json.Marshal fails, it returns 'unable to dump metas: %w'. The function's contract is that a context value must be serializable to JSON since the alert metadata is stored/transmitted as a JSON string.","triggerScenarios":"Called from TruncateContextMap with a values slice that cannot be marshaled. For plain []string this marshal cannot realistically fail; it is a defensive guard that would only trigger with a nil-vs-type anomaly or if the function were reused with other slice types.","commonSituations":"Practically unreachable in normal operation with []string inputs; encountered only if internals change or values somehow contain non-serializable content.","solutions":["Examine the wrapped error to understand the marshal failure","Ensure values passed to TruncateContext are []string","If it reproduces with valid []string input, file a bug — it indicates an internal invariant violation","Keep context values as plain UTF-8 strings in configuration and evaluation"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"if _, err := json.Marshal(values); err != nil {\n    return fmt.Errorf(\"values not marshallable: %w\", err)\n}","typeGuard":"func isStringSlice(v any) bool {\n    _, ok := v.([]string)\n    return ok\n}","tryCatchPattern":"s, err := alertcontext.TruncateContext(values, maxLen)\nif err != nil {\n    log.Errorf(\"truncate failed: %v\", err)\n    s = \"[]\" // safe fallback\n}","preventionTips":["Pass only []string to TruncateContext","Treat this error as an invariant violation and report it upstream","Cover TruncateContext in unit tests if you modify it","Avoid custom marshaling wrappers around context values"],"tags":["json","truncation","context"],"backgroundTag":"json-marshal-failed","analyzedSha":"909b5157986a2b2c2163300fdaef5ed01289f7d2","analyzedAt":"2026-09-06T12:27:26.012Z","contentChangedAt":"2026-09-06T12:27:26.012Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}