Exporting Org files with broken links

Given an Org file with a broken link:

This is a broken link!

When exporting this file through the export dispatcher or a publish project, publishing this file produces an error explaining that the file can’t be exported because it includes a broken link:

Publishing file example.org using ‘org-html-publish-to-html’
org-export-data: Unable to resolve link: "does-not-exist"

You can disable this error and export the file regardless of broken links by setting org-export-with-broken-links:

(setq org-export-with-broken-links t)

Now, generating the file produces an HTML page with the following contents:

This is !

Instead of generating with the broken link included—which is what you might expect to happen in this situation1—Org produced a file that has the link stripped out of the document completely.

Another option is “mark”, to clearly mark each broken link in the exported document:

(setq org-export-with-broken-links 'mark)

The result includes the link description in brackets, with the words “broken link” in all caps, to make the problem easier to spot:

This is [BROKEN LINK: does-not-exist]!

  1. The current implementation in ox.el stems from 2015 and makes sense from a technical perspective. It’s implemented as an error handler in the main exporting logic, and not in one of the exporters. This means that at the time the error happens, the exporter doesn’t know what kind of link to produce, which is an explanation why the links aren’t just left in.

      (&rest body)
      `(condition-case err
           (progn ,@body)
          (pcase (plist-get info :with-broken-links)
            (`nil (user-error "Unable to resolve link: %S" (nth 1 err)))
            (`mark (org-export-data
                    (format "[BROKEN LINK: %s]" (nth 1 err)) info))
            (_ nil))))))

    A solution to this might be to rewrite part of the error handling to allow it to ignore link errors.

    An simpler improvement could be is to put the link description in the document without making it a link.

    The broken link handler depends on signals raised from other places in the code. Depending on the org-export-with-broken-links variable, the handler raises an error, returns the marked link, or returns nothing.

    When configured to mark broken links, it takes the link out of the signal it received, but those signals don’t include the link descriptions. Also, there doesn’t seem to be a straightforward way do add them.