Skip to content

[Bug]: Accidental archiving of about:blank (and other pages) breaks date order and prevents showing new pages in archive list. #314

@Gamingappleh

Description

@Gamingappleh

ArchiveWeb.page Version

v0.15.7

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, to add entry to archive and not break ordered by date function.

However, sometimes about:blank (or other chrome pages) gets 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:

  1. breaks date ordering and
  2. causes new URLs added afterward to seemingly not appear (only in UI).

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.

This issue appears rarely and intermittently and under different conditions some include:

  • starting archiving from about:blank rather than a direct URL (ie. via go button).
  • Or clicking a link on currently archiving page with 'target="_blank"'.

Why start from about:blank?

  • Beginning on about:blank lets you capture intermediate and redirected URLs cleanly are included in the archive. (e.g 301 http response codes).
  • Also the "go" button (on index.html) seems to utilize this.

Additional details

I "fixed" my archive by going to extension page clicking into archive then clicking "inspect" then console. Pasted the following code and then deleting any pages (e.g about:blank) with ts=0 and deleting it manually. (Note: Although I have used this many times so far and checked the database use at own risk.)

(async () => {
  try {
    const extensionId = window.location.host;
    // Extract collection ID from URL params
    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');

    // Container setup
    const containerId = 'page-delete-ui';
    let container = document.getElementById(containerId);
    if (!container) {
      container = document.createElement('div');
      container.id = containerId;
      container.style.position = 'fixed';
      container.style.bottom = '10px';
      container.style.right = '10px';
      container.style.width = '440px';
      container.style.maxHeight = '580px';
      container.style.overflow = 'hidden';
      container.style.backgroundColor = 'rgba(255,255,255,0.96)';
      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);
    }

    // Tabs container
    container.innerHTML = '';
    const tabsBar = document.createElement('div');
    tabsBar.style.display = 'flex';
    tabsBar.style.marginBottom = '8px';
    tabsBar.style.gap = '10px';

    const tabs = {
      pages: { label: 'Pages in Collection' },
      files: { label: 'Individual File Search' }
    };

    const tabButtons = {};
    for (const key in tabs) {
      const btn = document.createElement('button');
      btn.textContent = tabs[key].label;
      btn.style.flex = '1';
      btn.style.cursor = 'pointer';
      btn.style.padding = '6px';
      btn.style.borderRadius = '4px';
      btn.style.border = '1px solid #888';
      btn.style.backgroundColor = key === 'pages' ? '#4CAF50' : '#eee';
      btn.style.color = key === 'pages' ? 'white' : 'black';
      tabButtons[key] = btn;
      tabsBar.appendChild(btn);
    }
    container.appendChild(tabsBar);

    const contentDivs = {};
    for (const key in tabs) {
      const div = document.createElement('div');
      div.style.height = '480px';
      div.style.overflowY = 'auto';
      div.style.display = key === 'pages' ? 'block' : 'none';
      container.appendChild(div);
      contentDivs[key] = div;
    }

    // === TAB 1: PAGES IN COLLECTION WITH DETAILED MULTI-MATCH SEARCH ===

    let pagesData = null;
    let pagesSortOldestFirst = true;
    let pagesFilterTsZero = false;
    let pagesSearchQuery = '';

    async function fetchPages() {
    const fetchUrl = `chrome-extension://${extensionId}/w/api/c/${collectionId}?all=1`;
    const response = await fetch(fetchUrl);
    if (!response.ok) throw new Error(`Failed fetching pages. Status: ${response.status}`);
    const data = await response.json();
    if (!data.pages || !Array.isArray(data.pages)) throw new Error('Pages array missing');
    pagesData = data.pages;
}

    function formatTs(ts) {
      try { return ts === 0 ? '0' : new Date(ts).toLocaleString(); }
      catch { return 'Invalid Date'; }
    }

    // Highlight and snippet generator: returns up to maxMatches snippets per text
    function findHighlightedSnippets(text, query, maxMatches = 5) {
      if (!text) return [];
      const escapedQuery = query.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
      const regex = new RegExp(escapedQuery, 'ig');
      let matches = [];
      let match;

      while ((match = regex.exec(text)) !== null && matches.length < maxMatches) {
        const matchIndex = match.index;
        const matchLength = match[0].length;

        if (text.includes('\n')) {
          const lines = text.split('\n');
          let charCount = 0;
          for (const line of lines) {
            if (matchIndex >= charCount && matchIndex < charCount + line.length) {
              const hlLine = line.replace(new RegExp(escapedQuery, 'ig'), m => `<mark style="background-color: yellow; padding:0;">${m}</mark>`);
              matches.push(hlLine);
              break;
            }
            charCount += line.length + 1;
          }
        } else {
          const startSnippet = Math.max(0, matchIndex - 15);
          const endSnippet = Math.min(text.length, matchIndex + matchLength + 15);
          let snippet = text.substring(startSnippet, endSnippet);
          if (startSnippet > 0) snippet = '...' + snippet;
          if (endSnippet < text.length) snippet = snippet + '...';
          const relativeMatchIndex = snippet.toLowerCase().indexOf(match[0].toLowerCase());
          if (relativeMatchIndex !== -1) {
            snippet = snippet.substring(0, relativeMatchIndex)
              + `<mark style="background-color: yellow; padding:0;">`
              + snippet.substring(relativeMatchIndex, relativeMatchIndex + matchLength)
              + `</mark>`
              + snippet.substring(relativeMatchIndex + matchLength);
          }
          matches.push(snippet);
        }
      }
      return matches;
    }

    const defaultVisibleAttrs = ['title', 'url', 'ts'];

    function renderPagesToolbar(parent) {
      parent.innerHTML = '';

      const header = document.createElement('h3');
      header.style.marginTop = '0';
      header.textContent = `Pages in Collection: ${collectionId}`;
      parent.appendChild(header);

      const toolbar = document.createElement('div');
      toolbar.style.marginBottom = '12px';
      toolbar.style.display = 'flex';
      toolbar.style.gap = '8px';
      toolbar.style.alignItems = 'center';

      const sortBtn = document.createElement('button');
      function updateSortBtnLabel() {
        sortBtn.textContent = pagesSortOldestFirst ? 'Sort: Oldest → Newest' : 'Sort: Newest → Oldest';
      }
      updateSortBtnLabel();
      sortBtn.style.flex = '1';
      sortBtn.style.cursor = 'pointer';
      sortBtn.style.padding = '6px';
      sortBtn.style.borderRadius = '4px';
      sortBtn.style.border = '1px solid #888';
      sortBtn.style.backgroundColor = '#f0f0f0';
      sortBtn.onclick = () => {
        pagesSortOldestFirst = !pagesSortOldestFirst;
        updateSortBtnLabel();
        renderPagesContent(parent);
      };

      const filterBtn = document.createElement('button');
      function updateFilterBtnLabel() {
        filterBtn.textContent = pagesFilterTsZero ? 'Showing ts=0 Only' : 'Show entries with ts=0';
        filterBtn.style.backgroundColor = pagesFilterTsZero ? '#d0f0d0' : '#f0f0f0';
      }
      updateFilterBtnLabel();
      filterBtn.style.flex = '1.5';
      filterBtn.style.cursor = 'pointer';
      filterBtn.style.padding = '6px';
      filterBtn.style.borderRadius = '4px';
      filterBtn.style.border = '1px solid #888';
      filterBtn.onclick = () => {
        pagesFilterTsZero = !pagesFilterTsZero;
        updateFilterBtnLabel();
        renderPagesContent(parent);
      };

      const searchInput = document.createElement('input');
      pagesSearchQuery = '';
      searchInput.type = 'search';
      searchInput.placeholder = 'Search...';
      searchInput.value = pagesSearchQuery;
      searchInput.style.flex = '2';
      searchInput.style.padding = '6px 8px';
      searchInput.style.borderRadius = '4px';
      searchInput.style.border = '1px solid #888';
      searchInput.autocomplete = 'off';
      searchInput.addEventListener('input', e => {
        pagesSearchQuery = e.target.value.trim();
        renderPagesContent(parent);
      });

      toolbar.appendChild(sortBtn);
      toolbar.appendChild(filterBtn);
      toolbar.appendChild(searchInput);
      parent.appendChild(toolbar);
    }

    function renderPagesContent(parent) {
      let pagesListDiv = parent.querySelector('.pages-list-container');
      if (pagesListDiv) pagesListDiv.remove();

      pagesListDiv = document.createElement('div');
      pagesListDiv.className = 'pages-list-container';
      pagesListDiv.style.maxHeight = '400px';
      pagesListDiv.style.overflowY = 'auto';
      parent.appendChild(pagesListDiv);

      if (!pagesData) {
        pagesListDiv.textContent = 'Loading...';
        return;
      }

      let filtered = pagesData;
      if (pagesFilterTsZero) filtered = filtered.filter(p => p.ts === 0);

      if (pagesSearchQuery) {
        const q = pagesSearchQuery.toLowerCase();
        // Filter for pages that match any attribute containing query
        filtered = filtered.filter(page =>
          Object.values(page).some(v => v && String(v).toLowerCase().includes(q))
        );
      }

      filtered.sort((a, b) => pagesSortOldestFirst ? a.ts - b.ts : b.ts - a.ts);

      if (filtered.length === 0) {
        const noPages = document.createElement('div');
        noPages.style.fontStyle = 'italic';
        noPages.textContent = 'No pages to display.';
        pagesListDiv.appendChild(noPages);
        return;
      }

      filtered.forEach(page => {
        const pageDiv = document.createElement('div');
        pageDiv.style.marginBottom = '10px';
        pageDiv.style.paddingBottom = '6px';
        pageDiv.style.borderBottom = '1px solid #ddd';

        // Capitalize attribute names for labels
        const capitalize = s => s.charAt(0).toUpperCase() + s.slice(1);

        // Render attribute with up to 5 highlighted snippets or normal values
        function renderAttribute(label, key, val, searchActive, query) {
          if (val == null) return '';
          if (key === 'title' && !val) val = '(No title)';
          if (key === 'ts') val = formatTs(val);

          if (searchActive && val && typeof val === 'string' && val.toLowerCase().includes(query.toLowerCase())) {
            let snippets = findHighlightedSnippets(val, query, 5);
            if (snippets.length === 0) snippets = [val]; // fallback whole text
            // Compose HTML block with label and all snippets each in separate div
            return `<div><strong>${label}:</strong>${snippets.map(snip => `<div style="margin-left:10px;">${snip}</div>`).join('')}</div>`;
          } else if (!searchActive) {
            if (key === 'url') {
              // URL with open upload button in non-search mode or unmatched
              return `<div style="display:flex; align-items:center; gap:6px; flex-wrap: wrap;">
                <strong>${label}:</strong>
                <a href="${val}" target="_blank" rel="noopener noreferrer" style="flex:1; min-width:0;">${val}</a>
                <button title="Open Upload" style="
                  padding: 2px 6px;
                  font-size: 12px;
                  cursor: pointer;
                  border-radius: 3px;
                  border: 1px solid #777;
                  background-color: #4CAF50;
                  color: white;
                  flex: none;
                  ">↗</button></div>`;
            }
            return `<div><strong>${label}:</strong> ${val}</div>`;
          } else {
            // For non-string or unmatched, just text
            if (key === 'url') {
              return `<div style="display:flex; align-items:center; gap:6px; flex-wrap: wrap;">
                <strong>${label}:</strong>
                <a href="${val}" target="_blank" rel="noopener noreferrer" style="flex:1; min-width:0;">${val}</a>
                <button title="Open Upload" style="
                  padding: 2px 6px;
                  font-size: 12px;
                  cursor: pointer;
                  border-radius: 3px;
                  border: 1px solid #777;
                  background-color: #4CAF50;
                  color: white;
                  flex: none;
                  ">↗</button></div>`;
            }
            return `<div><strong>${label}:</strong> ${val}</div>`;
          }
        }

        // Compose the HTML for this page, showing default visible attrs always with highlighted matches if searching
        let innerHTML = '';
        const searchActive = pagesSearchQuery.length > 0;
        const q = pagesSearchQuery;

        // Show Title, URL, Timestamp always
        innerHTML += renderAttribute('Title', 'title', page.title, searchActive, q);
        innerHTML += renderAttribute('URL', 'url', page.url, searchActive, q);
        innerHTML += renderAttribute('Timestamp', 'ts', page.ts, searchActive, q);

        // If searching, show other matched attributes with up to 5 snippets each
        if (searchActive) {
          const matchedAttrs = [];
          for (const [key, val] of Object.entries(page)) {
            if (!defaultVisibleAttrs.includes(key) && val != null) {
              if (typeof val === 'string' && val.toLowerCase().includes(q.toLowerCase())) {
                matchedAttrs.push(key);
              }
            }
          }
          matchedAttrs.forEach(attr => {
            innerHTML += renderAttribute(capitalize(attr), attr, page[attr], true, q);
          });
        }

        pageDiv.innerHTML = innerHTML;

        // Attach open upload button's click handler for the URL attribute's upload button
        const uploadBtn = pageDiv.querySelector('button[title="Open Upload"]');
        if (uploadBtn) {
          uploadBtn.onclick = () => {
            const openUrl = `chrome-extension://${extensionId}/index.html?source=local://${collectionId}#view=pages&url=${encodeURIComponent(page.url)}&ts=${page.ts}`;
            window.open(openUrl, '_blank');
          };
        }

        // 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://${extensionId}/w/api/c/${collectionId}/page/${page.id}`;
            const delResp = await fetch(deleteUrl, { method: 'DELETE' });
            if (delResp.ok) {
              const idx = pagesData.findIndex(p => p.id === page.id);
              if (idx !== -1) pagesData.splice(idx, 1);
              renderPagesContent(parent);
              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);

        pagesListDiv.appendChild(pageDiv);
      });
    }

    // === TAB 2: INDIVIDUAL FILE SEARCH ===

    let filesData = null;
    let filesSortOldestFirst = true;
    let filesSearchQuery = '';
    let filesMimeFilter = '';

    function formatDateISO(dateString) {
      try {
        const d = new Date(dateString);
        return d.toLocaleString();
      } catch {
        return 'Invalid Date';
      }
    }

    async function fetchFiles() {
      const mimeQuery = filesMimeFilter || '';
      const url = `chrome-extension://${extensionId}/w/api/c/${collectionId}/urls?mime=${mimeQuery}&url=&prefix=0&count=100`;
      const resp = await fetch(url);
      if (!resp.ok) throw new Error(`Failed fetching files. Status: ${resp.status}`);
      const obj = await resp.json();
      if (!obj.urls || !Array.isArray(obj.urls)) throw new Error('urls array missing');
      filesData = obj.urls.map(u => ({
        ...u,
        ts: Number(u.ts) || 0,
        dateObj: new Date(u.date),
      }));
    }

    function renderFilesToolbar(parent) {
      parent.innerHTML = '';

      const header = document.createElement('h3');
      header.style.marginTop = '0';
      header.textContent = `Individual Files in Collection: ${collectionId}`;
      parent.appendChild(header);

      const toolbar = document.createElement('div');
      toolbar.style.marginBottom = '12px';
      toolbar.style.display = 'flex';
      toolbar.style.gap = '8px';
      toolbar.style.alignItems = 'center';

      const sortBtn = document.createElement('button');
      function updateSortBtnLabel() {
        sortBtn.textContent = filesSortOldestFirst ? 'Sort: Oldest → Newest' : 'Sort: Newest → Oldest';
      }
      updateSortBtnLabel();
      sortBtn.style.flex = '1.2';
      sortBtn.style.cursor = 'pointer';
      sortBtn.style.padding = '6px';
      sortBtn.style.borderRadius = '4px';
      sortBtn.style.border = '1px solid #888';
      sortBtn.style.backgroundColor = '#f0f0f0';
      sortBtn.onclick = () => {
        filesSortOldestFirst = !filesSortOldestFirst;
        updateSortBtnLabel();
        renderFilesContent(parent);
      };

      const mimeFilter = document.createElement('select');
      mimeFilter.style.flex = '1.5';
      mimeFilter.style.padding = '6px 8px';
      mimeFilter.style.borderRadius = '4px';
      mimeFilter.style.border = '1px solid #888';
      mimeFilter.title = 'Filter by MIME type';

      const options = [
        { label: 'All URLs', value: '' },
        { label: 'Videos & Audio', value: 'audio%2F%2Cvideo%2F' }
      ];
      options.forEach(opt => {
        const option = document.createElement('option');
        option.value = opt.value;
        option.textContent = opt.label;
        if (opt.value === filesMimeFilter) option.selected = true;
        mimeFilter.appendChild(option);
      });

      mimeFilter.onchange = () => {
        filesMimeFilter = mimeFilter.value;
        fetchAndRenderFiles();
      };

      const searchInput = document.createElement('input');
      filesSearchQuery = '';
      searchInput.type = 'search';
      searchInput.placeholder = 'Search URLs or MIME types...';
      searchInput.value = filesSearchQuery;
      searchInput.style.flex = '2';
      searchInput.style.padding = '6px 8px';
      searchInput.style.borderRadius = '4px';
      searchInput.style.border = '1px solid #888';
      searchInput.autocomplete = 'off';
      searchInput.addEventListener('input', e => {
        filesSearchQuery = e.target.value.trim();
        renderFilesContent(parent);
      });

      toolbar.appendChild(sortBtn);
      toolbar.appendChild(mimeFilter);
      toolbar.appendChild(searchInput);
      parent.appendChild(toolbar);
    }

    function renderFilesContent(parent) {
      let filesListDiv = parent.querySelector('.files-list-container');
      if (filesListDiv) filesListDiv.remove();

      filesListDiv = document.createElement('div');
      filesListDiv.className = 'files-list-container';
      filesListDiv.style.maxHeight = '400px';
      filesListDiv.style.overflowY = 'auto';
      parent.appendChild(filesListDiv);

      if (!filesData) {
        filesListDiv.textContent = 'Loading...';
        return;
      }

      let filtered = filesData;
      if (filesSearchQuery) {
        const q = filesSearchQuery.toLowerCase();
        filtered = filtered.filter(f =>
          (f.url && f.url.toLowerCase().includes(q)) ||
          (f.mime && f.mime.toLowerCase().includes(q)) ||
          (String(f.ts).includes(q)) ||
          (String(f.status).includes(q))
        );
      }

      filtered.sort((a, b) => filesSortOldestFirst ? a.ts - b.ts : b.ts - a.ts);

      if (filtered.length === 0) {
        const noFiles = document.createElement('div');
        noFiles.style.fontStyle = 'italic';
        noFiles.textContent = 'No files to display.';
        filesListDiv.appendChild(noFiles);
        return;
      }

      filtered.forEach(file => {
        const fileDiv = document.createElement('div');
        fileDiv.style.marginBottom = '10px';
        fileDiv.style.paddingBottom = '6px';
        fileDiv.style.borderBottom = '1px solid #ddd';

        const urlContainer = document.createElement('div');
        urlContainer.style.display = 'flex';
        urlContainer.style.alignItems = 'center';
        urlContainer.style.gap = '6px';

        const urlLink = document.createElement('a');
        urlLink.href = file.url;
        urlLink.target = '_blank';
        urlLink.rel = 'noopener noreferrer';
        urlLink.style.flex = '1';
        urlLink.style.minWidth = '0';
        urlLink.textContent = file.url;

        const uploadBtn = document.createElement('button');
        uploadBtn.title = 'Open Upload';
        uploadBtn.textContent = '↗';
        uploadBtn.style.padding = '2px 6px';
        uploadBtn.style.fontSize = '12px';
        uploadBtn.style.cursor = 'pointer';
        uploadBtn.style.borderRadius = '3px';
        uploadBtn.style.border = '1px solid #777';
        uploadBtn.style.backgroundColor = '#4CAF50';
        uploadBtn.style.color = 'white';
        uploadBtn.onclick = () => {
          const openUrl = `chrome-extension://${extensionId}/index.html?source=local://${collectionId}#view=pages&url=${encodeURIComponent(file.url)}&ts=${file.ts}`;
          window.open(openUrl, '_blank');
        };

        urlContainer.appendChild(urlLink);
        urlContainer.appendChild(uploadBtn);
        fileDiv.appendChild(urlContainer);

        const mimeDiv = document.createElement('div');
        mimeDiv.innerHTML = `<strong>MIME:</strong> ${file.mime || 'N/A'}`;
        fileDiv.appendChild(mimeDiv);

        const dateDiv = document.createElement('div');
        dateDiv.innerHTML = `<strong>Date:</strong> ${formatDateISO(file.date)}`;
        fileDiv.appendChild(dateDiv);

        const tsDiv = document.createElement('div');
        tsDiv.innerHTML = `<strong>TS:</strong> ${file.ts}`;
        fileDiv.appendChild(tsDiv);

        const statusDiv = document.createElement('div');
        statusDiv.innerHTML = `<strong>Status:</strong> ${file.status}`;
        fileDiv.appendChild(statusDiv);

        filesListDiv.appendChild(fileDiv);
      });
    }

    async function fetchAndRenderFiles() {
      try {
        filesData = null;
        renderFilesToolbar(contentDivs.files);
        renderFilesContent(contentDivs.files);
        const filesListDiv = contentDivs.files.querySelector('.files-list-container');
        if (filesListDiv) filesListDiv.textContent = 'Loading...';
        await fetchFiles();
        renderFilesContent(contentDivs.files);
      } catch (err) {
        contentDivs.files.innerHTML = `<div style="color:red;">Error loading files: ${err.message}</div>`;
      }
    }

    async function initialize() {
      await fetchPages();
      renderPagesToolbar(contentDivs.pages);
      renderPagesContent(contentDivs.pages);
      renderFilesToolbar(contentDivs.files);

      let filesLoaded = false;
      for (const key in tabButtons) {
        tabButtons[key].onclick = async () => {
          for (const t in tabs) {
            tabButtons[t].style.backgroundColor = (t === key) ? '#4CAF50' : '#eee';
            tabButtons[t].style.color = (t === key) ? 'white' : 'black';
            contentDivs[t].style.display = (t === key) ? 'block' : 'none';
          }
          if (key === 'files' && !filesLoaded) {
            await fetchAndRenderFiles();
            filesLoaded = true;
          }
        };
      }
    }

    await initialize();

  } catch (error) {
    console.error('Error:', 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 added due to the invalid timestamp. These may be related issues to:

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