id: no-swallowed-error
language: rust
severity: warning
category: correctness
message: "Source error discarded. Preserve context with .context() or map_err(|e| ...e...)."
note: "map_err(|_| ...) throws away the original error, making debugging impossible. Propagating with ? after map_err is a valid conversion, not swallowing."
rule:
any:
- all:
- kind: call_expression
- has:
field: function
kind: field_expression
has:
field: field
regex: '^map_err$'
- has:
field: arguments
regex: '^\(\s*\|_\w*\|'
- not:
inside:
kind: try_expression
stopBy: end
- all:
- kind: macro_invocation
- regex: '^[\w:]+!\s*[(\[]'
- regex: '\.map_err\(\|_\w*\|'
- not:
inside:
kind: try_expression
stopBy: end
ignores:
- "**/tests/**"
- "**/*_tests/**"
- "**/*_test/**"
- "**/test_*"
- "**/*_test.rs"
- "**/fixtures/**"
skip_test_code: true
tests:
should_match:
- 'file.read_to_string(&mut buf).map_err(|_| AppError::ReadFailed);'
- 'conn.execute(sql).map_err(|_e| Error::Database);'
should_not_match:
- 'file.read_to_string(&mut buf).map_err(|e| AppError::Io(e));'
- 'conn.execute(sql).map_err(AppError::Database);'
- 'conn.execute(sql).map_err(|_| Error::Database)?;'
- 'decode_header(token).map_err(|_| AuthError::InvalidToken)?;'
- 'let v = Some(x.parse().map_err(|_| Error::Bad)?);'