{"record":{"id":"cd93b4234f778b26","repo":"astral-sh/ruff","slug":"flag-reason-cannot-contain-newline-characters","errorCode":null,"errorMessage":"{flag} <reason> cannot contain newline characters","messagePattern":"(.+?) <reason> cannot contain newline characters","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/ruff/src/lib.rs","lineNumber":338,"sourceCode":"        warn_user!(\"Detected debug build without --no-cache.\");\n    }\n\n    let suppression = cli\n        .add_noqa\n        .as_ref()\n        .map(|reason| (reason, SuppressionKind::Noqa, \"--add-noqa\"))\n        .or_else(|| {\n            cli.add_ignore\n                .as_ref()\n                .map(|reason| (reason, SuppressionKind::Ignore, \"--add-ignore\"))\n        });\n\n    if let Some((reason, suppression_kind, flag)) = suppression {\n        if !fix_mode.is_generate() {\n            warn_user!(\"--fix is incompatible with {flag}.\");\n        }\n        if reason.contains(['\\n', '\\r']) {\n            return Err(anyhow::anyhow!(\n                \"{flag} <reason> cannot contain newline characters\"\n            ));\n        }\n\n        let reason_opt = (!reason.is_empty()).then_some(reason.as_str());\n\n        let modifications = commands::add_noqa::add_noqa(\n            &files,\n            &pyproject_config,\n            &config_arguments,\n            reason_opt,\n            suppression_kind,\n        )?;\n        if modifications > 0 && config_arguments.log_level >= LogLevel::Default {\n            let s = if modifications == 1 { \"\" } else { \"s\" };\n            let suppression = match suppression_kind {\n                SuppressionKind::Noqa => \"noqa directive\",\n                SuppressionKind::Ignore => \"ignore comment\",","sourceCodeStart":320,"sourceCodeEnd":356,"githubUrl":"https://github.com/astral-sh/ruff/blob/672bb4edf04c84f8b0753346359daee4057158f2/crates/ruff/src/lib.rs#L320-L356","documentation":"`ruff check --add-noqa [reason]` and `--add-ignore [reason]` embed the reason into generated suppression comments; a newline would corrupt the comment syntax, so any '\\n' or '\\r' in the reason is rejected before work starts.","triggerScenarios":"Passing a multi-line reason, e.g. `ruff check --add-noqa \"$(printf 'see #123\\nfollow-up')\"`, or a reason variable containing line breaks from a heredoc/file read.","commonSituations":"CI scripts building reasons from PR descriptions or multi-line files; shell quoting with $'...' that inserts \\n; copy-pasting reasons with trailing line breaks.","solutions":["Strip newlines first: `ruff check --add-noqa \"$(printf '%s' \"$reason\" | tr -d '\\r\\n')\"`","Keep the reason to one line and link the ticket instead","If you also pass --fix, remove it: it is incompatible with --add-noqa/--add-ignore (warned separately)"],"exampleFix":"# before\nruff check --add-noqa \"$MULTILINE_REASON\" src/\n\n# after\nruff check --add-noqa \"$(printf '%s' \"$MULTILINE_REASON\" | tr -d '\\r\\n')\" src/","handlingStrategy":"validation","validationCode":"reason=$(printf '%s' \"$reason\" | tr -d '\\r\\n')\nruff check --add-noqa \"$reason\" \"$target\"","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Normalize reasons to a single line at the source (script, config, CI variable)","Avoid building reasons from heredocs or multi-line files","Put long explanations in the linked ticket, not in the reason string"],"tags":["cli","suppressions","validation"],"backgroundTag":null,"analyzedSha":"672bb4edf04c84f8b0753346359daee4057158f2","analyzedAt":"2026-08-16T08:54:05.464Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}