Skip to content

[Bug]: Accidental archiving of about:blank breaks date order and prevents showing new archiving. #314

@Gamingappleh

Description

@Gamingappleh

ArchiveWeb.page Version

v0.15.3

What did you expect to happen? What happened instead?

When starting an archiving session via the "go" button on index.html or starting an archive on about:blank, I expect the archive to start cleanly and for new URLs to be correctly ordered by date.

However, sometimes about:blank gets inadvertently included in the archive with a timestamp (ts) of 0. While usually about:blank is not part of the archive and the first URL is, this occasional inclusion breaks date ordering and causes new URLs added afterward to seemingly not appear.

How can I tell it’s happened?

Querying the collection data via:

chrome-extension://fpeoodllldobpkbkabpblcfaogecpndd/w/api/c/${collectionId}?all=1

reveals an entry like:

{
  "url": "about:blank",
  "ts": 0,
  ...
}

Additionally, the console throws this error:

Uncaught (in promise) RangeError: Invalid time value
    at Date.toISOString ()
    at mt (ui.js:136:2457)
    ...

Pointing to the following method:

function mt(e) {
  try {
    t = new Date(e.ts || [e.date]);
  } catch (e) {}
  const i = t && t instanceof Date ? bt(t.toISOString()) : "";
  return {
    date: t,
    timestamp: i
  }
}

Step-by-step reproduction instructions

This issue appears rarely and intermittently. It seems related to starting archiving from about:blank rather than a direct URL.

Here is a rough visual explanation of a typical navigation sequence that can lead to the issue:

1. Start recording on about:blank
   (This blank start allows capturing URLs that perform redirects)

          ↓

2. Navigate to https://www.example.com/
   (The main site loads and is archived)

          ↓

3. Navigate back to about:blank
   (User returns to a blank page before entering a new URL)

          ↓

4. Paste a URL in the address bar, e.g. https://www.example.com/redirect
   (This URL redirects to a final destination)

          ↓

5. The redirect leads to https://www.example.com/home
   (The redirected page is loaded and archived)

Why start from about:blank?

  • Beginning on about:blank lets you capture intermediate and redirected URLs cleanly.
  • It ensures all navigation steps—including redirects—are included in the archive.
  • This approach is useful for complex sites where the final destination is not immediately loaded.

Other than that, no consistent repro steps. The presence of the about:blank URL with a timestamp of 0 appears to be the root cause.

Additional details

I "fixed" my archive by injecting code in console to identify the corrupted about:blank page with ts=0 and deleting it manually (though this did not update resources tab, also unsure if this will tamper or affect export logic):

(async () => {
  try {
    // Extract collection ID
    const urlObj = new URL(window.location.href);
    const sourceParam = urlObj.searchParams.get('source');
    const collectionId = sourceParam ? sourceParam.replace('local://', '') : null;
    if (!collectionId) throw new Error('Collection ID not found in URL');

    // Fetch collection pages data
    const fetchUrl = `chrome-extension://fpeoodllldobpkbkabpblcfaogecpndd/w/api/c/${collectionId}?all=1`;
    const response = await fetch(fetchUrl);
    if (!response.ok) throw new Error(`Failed fetching collection. Status: ${response.status}`);
    const data = await response.json();

    if (!data.pages || !Array.isArray(data.pages)) throw new Error('Pages array missing in collection data');

    // Create or get floating UI container
    let container = document.getElementById('page-delete-ui');
    if (!container) {
      container = document.createElement('div');
      container.id = 'page-delete-ui';
      container.style.position = 'fixed';
      container.style.bottom = '10px';
      container.style.right = '10px';
      container.style.width = '400px';
      container.style.maxHeight = '500px';
      container.style.overflowY = 'auto';
      container.style.backgroundColor = 'rgba(255,255,255,0.95)';
      container.style.border = '1px solid #ccc';
      container.style.padding = '10px';
      container.style.fontFamily = 'Arial, sans-serif';
      container.style.fontSize = '13px';
      container.style.zIndex = '1000000';
      container.style.borderRadius = '6px';
      container.style.boxShadow = '0 2px 12px rgba(0,0,0,0.2)';
      document.body.appendChild(container);
    }

    // Clear previous contents
    container.innerHTML = `<h3 style="margin-top:0;">Pages in Collection: ${collectionId}</h3>`;

    // Helper to format timestamp to readable string
    const formatTs = ts => {
      try {
        return new Date(ts).toLocaleString();
      } catch {
        return 'Invalid Date';
      }
    };

    // Render each page's info and delete button
    data.pages.forEach(page => {
      const pageDiv = document.createElement('div');
      pageDiv.style.marginBottom = '10px';
      pageDiv.style.paddingBottom = '6px';
      pageDiv.style.borderBottom = '1px solid #ddd';
      pageDiv.id = `page-${page.id}`;

      pageDiv.innerHTML = `
        <div><strong>Title:</strong> ${page.title || '(No title)'}</div>
        <div><strong>URL:</strong> <a href="${page.url}" target="_blank" rel="noopener noreferrer">${page.url}</a></div>
        <div><strong>Timestamp:</strong> ${formatTs(page.ts)}</div>
      `;

      // Create delete button
      const delBtn = document.createElement('button');
      delBtn.textContent = 'Delete';
      delBtn.style.marginTop = '6px';
      delBtn.style.padding = '4px 8px';
      delBtn.style.backgroundColor = '#e74c3c';
      delBtn.style.color = 'white';
      delBtn.style.border = 'none';
      delBtn.style.borderRadius = '3px';
      delBtn.style.cursor = 'pointer';

      delBtn.onclick = async () => {
        const confirmed = window.confirm(`Confirm deletion of page:\n\n${page.title}\n${page.url}`);
        if (!confirmed) return;

        try {
          delBtn.disabled = true;
          delBtn.textContent = 'Deleting...';

          const deleteUrl = `chrome-extension://fpeoodllldobpkbkabpblcfaogecpndd/w/api/c/${collectionId}/page/${page.id}`;
          const delResp = await fetch(deleteUrl, { method: 'DELETE' });

          if (delResp.ok) {
            container.removeChild(pageDiv);
            alert('Page deleted successfully.');
          } else {
            alert(`Failed to delete page. Status: ${delResp.status}`);
            delBtn.disabled = false;
            delBtn.textContent = 'Delete';
          }
        } catch (err) {
          alert('Error deleting page: ' + err.message);
          delBtn.disabled = false;
          delBtn.textContent = 'Delete';
        }
      };

      pageDiv.appendChild(delBtn);
      container.appendChild(pageDiv);
    });
  } catch (error) {
    console.error('Error loading or deleting pages:', error);
    alert('Error: ' + error.message);
  }
})();

Since this bug disrupts/breaks the chronological order in the archive UI and effectively blocks new URLs from showing after about:blank is inserted due to the invalid timestamp. These may be related issues:

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions