Skip to content

Replace error logging with silent skip when page DNE#2885

Open
MoshiMoshiMochi wants to merge 7 commits intoMarkBind:masterfrom
MoshiMoshiMochi:bug/pagefind-resolve-serve-onepage-error
Open

Replace error logging with silent skip when page DNE#2885
MoshiMoshiMochi wants to merge 7 commits intoMarkBind:masterfrom
MoshiMoshiMochi:bug/pagefind-resolve-serve-onepage-error

Conversation

@MoshiMoshiMochi
Copy link
Copy Markdown
Contributor

@MoshiMoshiMochi MoshiMoshiMochi commented Apr 6, 2026

Pages that exist get indexed normally while pages that don't are skipped silently without returning an error message for missing pages.

What is the purpose of this pull request?

  • Documentation update
  • Bug fix
  • Feature addition or enhancement
  • Code maintenance
  • DevOps
  • Improve developer experience
  • Others, please explain:

Overview of changes:
#2882
Replace error logging with silent skip if page does not exist when serving one-page.

Anything you'd like to highlight/discuss:

There should no longer be any pagefind related indexing errors when serving one-page.
image

This issue arose from #2880, where I began switching the searchable page logic to respect page's option. It was an oversight an oversight by me during development as I had only tested the indexing with a full build. However, using markbind serve -o only the landing page is built at startup. The sitePages.pages array contains all pages defined in site.json, but most of their HTML files haven't been generated yet as they are built on-demand when u navigate to them.

As prof @damithc mentioned,

In fact it is because these pages don't exist when using -o flag. I think we should not show those as errors in the console, as missing pages is expected when using -o mode.

Hence, I added a check if a file exist first. If it doesn't & is serving one-page, silently skip to the next file to index. This ensures that the failed to index error doesn't occur because the file did not exist.

This is 100% my bad and on me, my apologies for not realising this earlier. Will be sure to be more thorough when testing out newly added/updated features in the future.

Testing instructions:

Proposed commit message: (wrap lines at 72 characters)

Add silent skip when indexing a page that does not exist


Checklist: ☑️

  • Updated the documentation for feature additions and enhancements
  • Added tests for bug fixes or features
  • Linked all related issues
  • No unrelated changes

Reviewer checklist:

Indicate the SEMVER impact of the PR:

  • Major (when you make incompatible API changes)
  • Minor (when you add functionality in a backward compatible manner)
  • Patch (when you make backward compatible bug fixes)

At the end of the review, please label the PR with the appropriate label: r.Major, r.Minor, r.Patch.

Breaking change release note preparation (if applicable):

  • To be included in the release note for any feature that is made obsolete/breaking

Give a brief explanation note about:

  • what was the old feature that was made obsolete
  • any replacement feature (if any), and
  • how the author should modify his website to migrate from the old feature to the replacement feature (if possible).

Pages that exist get indexed normally while pages that don't are skipped
silently without returning an error message for missing pages.
Included a check for if serving using onepage so that the error is still
raised if the file does not exist when the user serves a full build.
@codecov
Copy link
Copy Markdown

codecov bot commented Apr 6, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 71.32%. Comparing base (b3b90c8) to head (ec292de).

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #2885      +/-   ##
==========================================
- Coverage   71.35%   71.32%   -0.03%     
==========================================
  Files         133      133              
  Lines        7229     7232       +3     
  Branches     1611     1682      +71     
==========================================
  Hits         5158     5158              
- Misses       2065     2068       +3     
  Partials        6        6              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@MoshiMoshiMochi MoshiMoshiMochi marked this pull request as ready for review April 6, 2026 11:20
@MoshiMoshiMochi MoshiMoshiMochi requested a review from a team April 6, 2026 11:20
@gerteck
Copy link
Copy Markdown
Member

gerteck commented Apr 6, 2026

no worries @MoshiMoshiMochi , it is but a edge case that is not breaking 😄

Speedy quick fix!

if anything, these nits should be caught by the PR reviewer as well 😅

It could also mean our testcases are not comprehensive enough, to which we can improve on!

@MoshiMoshiMochi
Copy link
Copy Markdown
Contributor Author

As discussed, I've update enabling pagefind to its' own option where it is disabled by default. Users will now what to enable it within by declaring the pagefind configuration and setting enablePagefind to true

{
  "pagefind": {
    "enablePagefind": true
  }
}

Hence, as it is no longer tied to enableSearch which is true by default, all functional tests no longer captures pagefind.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is it truly the best way to do this? can we just skip indexing the site when serving one page?
We can add this.onePagePath to the if clause on line 319 to skip indexing altogether.

on another note, unrelated but curious, why is the pagefind import done this way?

import * as pagefind from 'pagefind';
const { createIndex, close } = pagefind;

instead of just doing

import { createIndex, close } from 'pagefind';

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Input just for the curiosity part

For some reason, the official docs' code snippet (which was probably used as the first draft) as on https://pagefind.app/docs/node-api/ also does it that way

image

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is it truly the best way to do this? can we just skip indexing the site when serving one page?
We can add this.onePagePath to the if clause on line 319 to skip indexing altogether.

I see where you're coming from and technically we could since this is kind of a band-aid fix. But ideally pagefind will support incremental page indexing like the current built-in search does (which I am working on it in this PR. And I guess logically speaking if the user were to serve with just one-page, they might expect it to index that page (though it is kinda useless without the incremental indexing).

As such, right now there is an overall incompatibility between indexSiteWithPagefind when serving one-page as the errors raised were because.

The sitePages.pages array contains all pages defined in site.json, but most of their HTML files haven't been generated yet as they are built on-demand when u navigate to them.

And the current fix will be more compatible with the changes made in #2890


Regarding the curiosity, honestly I don't think there's a difference. As @gerteck mentioned, the official docs does it that way so I kinda just followed suit.

But my guess would be that by only referencing const { createIndex, close } = pagefind; within indexSiteWithPagefind directly, we kinda keep the global scope of SiteGenerationManager cleaner. createIndex() & close() are kinda generic function names (well maybe less so createIndex). So if for some reason we needed to use another close() method from a different interface we could potentially face naming collision issues.

But hey this is just my speculation and justification for keeping the imports this way.

Also I've kinda mocked my testcases to these namespace imports so if we do decide to change it, maybe we could do it in another PR lol.

Copy link
Copy Markdown
Contributor

@yihao03 yihao03 Apr 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

on @gerteck 's screenshot from the official site, I think it's not exactly what's happening here? The example invokes the createIndex() method on the pagefind object while here, we are destructuring the createIndex() function from the pageFind object.

we kinda keep the global scope of SiteGenerationManager cleaner. createIndex() & close() are kinda generic function names

right right i never thought of that!

And I guess logically speaking if the user were to serve with just one-page, they might expect it to index that page

Doesn't this implementation indiscriminately skip all pages?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't this implementation indiscriminately skip all pages?

Not quite. Based on these fixes, pagefind will still index the respective page when serving just one-page. It just doesn't log the file DNE exist error when serving one-page as it isn't applicable in this case.

In the case of serving one-page, only the first page will be indexed (assuming of course that the first page is searchable).

const indexingResults = await Promise.all(
            searchablePages.map(async (page) => {
              const fileExists = await fs.pathExists(page.pageConfig.resultPath);
              if (!fileExists && this.onePagePath) {
                return null;
              }
              try {
                const content = await fs.readFile(page.pageConfig.resultPath, 'utf8');
                const relativePath = path.relative(this.outputPath, page.pageConfig.resultPath);

                return index.addHTMLFile({
                  sourcePath: relativePath,
                  content,
                });
              } catch (error) {
                logger.error(`Failed to index ${page.pageConfig.resultPath}: ${error}`);
                return null;
              }
            }),
          );

Of course this isn't the best fix as it means Pagefind will still iterate through all searchable pages only to skip most of them. However, this will be more explicitly addressed in the #2890 where there is a way of just indexing specific pages when needed.

Either ways, I still feel that this current "band-aid" fix is valuable as it serves as an additional layer of protection (from inaccurate logs) in case indexSiteWithPagefind is called when serving one-page.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants