iOfficeAI/OfficeCLI · error · MarkRejectedException

{error}

Error message

{error}

What it means

Thrown by WatchNotifier.AddMark when the running watch server returned a non-blank Error in its MarkResponse. The CLI distinguishes a pipe/timeout failure (returns null = 'no watch running') from a real server-side rejection (throws MarkRejectedException) so the user sees the actual cause (e.g. invalid regex, bad color/path) instead of an empty id being treated as success. BUG-FUZZER-R3-M01 made the check IsNullOrWhiteSpace so a whitespace-only error no longer spuriously throws.

Source

Thrown at src/officecli/Core/Watch/WatchNotifier.cs:182

                writer.WriteLine("mark " + payload);
                writer.Flush();

                using var reader = new StreamReader(client, noBom, detectEncodingFromByteOrderMarks: false, leaveOpen: true);
                var responseLine = reader.ReadLine();
                if (string.IsNullOrEmpty(responseLine)) { result = null; return; }
                var resp = JsonSerializer.Deserialize(responseLine, WatchMarkJsonContext.Default.MarkResponse);
                // BUG-FUZZER-R3-M01: use IsNullOrWhiteSpace for symmetry with the
                // server-side path/color validation. A whitespace-only error string
                // would otherwise spuriously throw MarkRejectedException.
                if (!string.IsNullOrWhiteSpace(resp?.Error)) { error = resp!.Error; return; }
                result = string.IsNullOrEmpty(resp?.Id) ? null : resp.Id;
            }, PipeTimeout);
        }
        catch
        {
            return null; // no watch running, or pipe failure
        }
        if (error != null) throw new MarkRejectedException(error);
        return result;
    }

    /// <summary>
    /// Remove marks from the running watch process. Returns count removed,
    /// or null if no watch is running.
    /// </summary>
    public static int? RemoveMarks(string filePath, UnmarkRequest request)
    {
        try
        {
            int? result = null;
            RunWithTimeout(() =>
            {
                var pipeName = WatchServer.GetWatchPipeName(filePath);
                using var client = new NamedPipeClientStream(".", pipeName, PipeDirection.InOut);
                client.Connect(200);

View on GitHub (pinned to 1ced45e900)

Solutions

  1. Read the exception Message — it carries the server's verbatim Error reason.
  2. Fix the offending field: correct the regex, use a supported color, fix the path/selector.
  3. Retry the mark once the input is valid.

Example fix

// before
var id = WatchNotifier.AddMark(file, new MarkRequest { Find = "(unclosed", Color = "red" });
// after
var id = WatchNotifier.AddMark(file, new MarkRequest { Find = "\\(closed\\)", Color = "red" });
Defensive patterns

Strategy: try-catch

Validate before calling

// Validate the find string as a regex before sending if regex=true
if (request.Regex && !IsValidRegex(request.Find))
    throw new InvalidOperationException("invalid regex in mark request");
static bool IsValidRegex(string p) { try { _ = new System.Text.RegularExpressions.Regex(p); return true; } catch { return false; } }

Try / catch

string? id;
try { id = WatchNotifier.AddMark(filePath, request); }
catch (MarkRejectedException ex)
{ /* ex.Message is the watch server's rejection reason; fix and retry */ id = null; }
if (id == null) { /* no watch running, or rejected */ }

Prevention

When it happens

Trigger: Calling AddMark (or the mark command) while a watch is running, with a MarkRequest the server rejects: an invalid/uncompilable regex find string, an unsupported color, a malformed path/selector, or any server-side validation failure that populates the Error field.

Common situations: User passes an invalid regex (e.g. unbalanced '('), a color the server does not accept, or a malformed highlight path; the watch server's validation rejects it and echoes the reason.

Related errors


AI-assisted analysis of iOfficeAI/OfficeCLI@1ced45e900 (2026-08-13). Data as JSON: /api/errors/d561e2f425209c78. Report an issue: GitHub.