{"record":{"id":"90e6e98d3fb1fe02","repo":"Hmbown/CodeWhale","slug":"pty-rows-and-columns-must-each-be-between-1-and-1000","errorCode":null,"errorMessage":"PTY rows and columns must each be between 1 and 1000","messagePattern":"PTY rows and columns must each be between 1 and 1000","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/tools/shell.rs","lineNumber":983,"sourceCode":"\n/// Cell dimensions accepted by the existing PTY owner. Pixel sizes remain\n/// unspecified; callers must not allocate an unbounded terminal grid.\n#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]\n#[serde(deny_unknown_fields)]\npub struct PtyDimensions {\n    pub rows: u16,\n    pub cols: u16,\n}\n\nimpl Default for PtyDimensions {\n    fn default() -> Self {\n        Self { rows: 24, cols: 80 }\n    }\n}\n\nimpl PtyDimensions {\n    pub fn validate(self) -> Result<Self> {\n        anyhow::ensure!(\n            (1..=1000).contains(&self.rows) && (1..=1000).contains(&self.cols),\n            \"PTY rows and columns must each be between 1 and 1000\"\n        );\n        Ok(self)\n    }\n}\n\n/// A background shell process being tracked\npub struct BackgroundShell {\n    pub id: String,\n    pub command: String,\n    pub working_dir: PathBuf,\n    pub status: ShellStatus,\n    pub exit_code: Option<i64>,\n    pub started_at: Instant,\n    /// When the job reached a terminal status. A finished job reports the\n    /// duration it finished with; without this, `started_at.elapsed()` kept\n    /// growing and `/jobs` showed \"2m 07s\" for a 12-second command (#5478).","sourceCodeStart":965,"sourceCodeEnd":1001,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/src/tools/shell.rs#L965-L1001","documentation":"PtyDimensions::validate enforces that both the PTY row and column counts are within the inclusive range 1..=1000 before a pseudo-terminal is created. This guards the TUI shell tool against callers passing nonsensical terminal sizes (zero, negative, or absurdly large) that would break downstream PTY allocation APIs. It is thrown via anyhow::ensure! when either dimension falls outside that range.","triggerScenarios":"Calling shell tool code paths that construct a PtyDimensions (or accept rows/cols from the caller/request) where rows or cols is 0, negative, or greater than 1000, then calling validate().","commonSituations":"A client or LLM tool call supplies `rows: 0` or omits/JSON-encodes a bad default for terminal size; a caller converts a window size using unsigned arithmetic that underflows to 0; a serialized dimensions struct from an older client carries out-of-range values.","solutions":["Check the rows/cols values passed into the shell tool call and clamp them to 1..=1000 before invoking.","If dimensions are absent, use the default (24x80) rather than 0.","Verify any unsigned-to-signed conversion of terminal sizes is not underflowing to 0 or wrapping."],"exampleFix":"// before\nlet pty = PtyDimensions { rows: 0, cols: 0 }.validate()?;\n\n// after\nlet pty = PtyDimensions {\n    rows: rows.clamp(1, 1000),\n    cols: cols.clamp(1, 1000),\n}\n.validate()?;","handlingStrategy":"validation","validationCode":"fn valid_pty(rows: i32, cols: i32) -> bool {\n    (1..=1000).contains(&rows) && (1..=1000).contains(&cols)\n}\n// call before issuing the shell request:\n// assert!(valid_pty(rows, cols), \"terminal size must be 1..=1000\");","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Clamp client-supplied rows/cols to 1..=1000 before sending.","Default to 24x80 when terminal size is unknown.","Never build dimensions from unchecked unsigned subtraction."],"tags":["pty","validation","terminal","argument-validation"],"backgroundTag":"value-out-of-range","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}