phacility/phabricator · error · Exception

Unable to find lines.

Error message

Unable to find lines.

What it means

Second-stage invariant in the same build-log renderer: the anchor byte was found inside a fetched data window, but none of the per-line records built from that data (each spanning [line.offset, line.offset+line.length), with an exclusive end) contains it. Unlike the fetch check, the line check uses a strictly greater end bound, so an anchor sitting exactly at the end of the data (e.g. offset == log size) or an empty/zero-line fetch matches no line even though it matched the window.

Source

Thrown at src/applications/harbormaster/controller/HarbormasterBuildLogRenderController.php:188

      if ($data_key === null) {
        throw new Exception(
          pht('Unable to find fetch!'));
      }

      $anchor_key = null;
      foreach ($reads[$data_key]['lines'] as $line_key => $line) {
        $s = $line['offset'];
        $e = $s + $line['length'];

        if (($s <= $anchor_byte) && ($e > $anchor_byte)) {
          $anchor_key = $line_key;
          break;
        }
      }

      if ($anchor_key === null) {
        throw new Exception(
          pht(
            'Unable to find lines.'));
      }

      if ($view['direction'] > 0) {
        $slice_offset = $anchor_key;
      } else {
        $slice_offset = max(0, $anchor_key - ($view['lines'] - 1));
      }
      $slice_length = $view['lines'];

      $views[$view_key] += array(
        'sliceKey' => $data_key,
        'sliceOffset' => $slice_offset,
        'sliceLength' => $slice_length,
      );
    }

View on GitHub (pinned to 5720a38cfe)

Solutions

  1. Reload the log URL fresh (drop headOffset/tailOffset/lines parameters) so the view offsets are recomputed against the current log.
  2. Verify the log's chunk data is intact (chunk table vs recorded length) if one specific log always fails.
  3. If you maintain this code, clamp the anchor into the last line when it lands at EOF instead of throwing (treat anchor == end of data as the final line).

Example fix

// before
if ($anchor_key === null) {
  throw new Exception(pht('Unable to find lines.'));
}

// after
if ($anchor_key === null) {
  $line_data = $reads[$data_key]['lines'];
  if ($line_data && $anchor_byte >= $log_size - 1) {
    $anchor_key = last_key($line_data);
  }
}
if ($anchor_key === null) {
  throw new Exception(pht('Unable to find lines.'));
}
Defensive patterns

Strategy: validation

Validate before calling

// Only request line-anchored views strictly inside the data:
if ($view['offset'] >= $log_size) {
  $view['offset'] = max(0, $log_size - 1);
}
// Skip views whose clamped fetch length is zero (fetchOffset already at EOF)

Try / catch

try {
  $anchor_key = findAnchorLine($reads, $anchor_byte);
} catch (Exception $e) {
  $anchor_key = last_key($reads[$data_key]['lines']); // degrade to last line
}

Prevention

When it happens

Trigger: A view whose offset equals the log's total size (nothing left to read forward), a fetch whose length was clamped to zero because fetchOffset already sits at EOF, or line-map markers whose recorded offsets run ahead of the actual chunk data (corrupted or half-archived log).

Common situations: Scrolling/paging to the very end of a log that has no trailing newline; requesting the tail of a log that shrank during archival; corrupted chunk tables making the computed line offsets not cover the anchor.

Related errors


AI-assisted analysis of phacility/phabricator@5720a38cfe (2026-08-21). Data as JSON: /api/errors/c8a7c02cb66c7ef6. Report an issue: GitHub.