Skip to content

fix(server): a ledger of another version says where it is, what to do and where to ask - #273

Merged
rami-hatoum merged 2 commits into
mainfrom
fix/ledger-shape-notice
Oct 21, 2026
Merged

rami-hatoum merged 2 commits into
mainfrom
fix/ledger-shape-notice

Conversation

@SamHatoum

@SamHatoum SamHatoum commented Oct 20, 2026 •

Copy link
Copy Markdown
Collaborator

What this changes

When the ledger's database was made by another version of Auto Runtime, the runtime refuses to start, as it is meant to: nothing is carried over before launch. But the words it stopped with were the ledger's own sentence wrapped twice, StartupError: The server's services could not start: Error: ..., telling the person to delete "the local database" without saying where it was, and telling a ledger in PostgreSQL to delete a local file it does not have.

Now:

  • The ledger refuses such a table as a LedgerShapeRefused, naming the table, what it holds, and the columns found and kept. Its message is unchanged.
  • The server turns that refusal into its own words, since it knows where the ledger is kept: the file's absolute path, or the PostgreSQL database and its host, never the URL; that this version keeps that data in a different shape and cannot read what this ledger holds; what to do; and where to ask. Where the ledger is kept is said by one function, shared with the start log.
  • Started in a terminal, the runtime shows this as a notice beneath the logo, styled like the ready notice, with the three files to delete named one by one, the ledger file and the -wal and -shm files SQLite keeps beside it, each quoted for the shell, so the command works in every POSIX shell and on a path with a space or a quote. In the image, where the files are on a volume, the notice says which files to delete from the volume instead of a command. A ledger in PostgreSQL is told to point DATABASE_URL at an empty database.
  • Started as a server (the image, or main.ts), the runtime says the same thing on its single line of stderr, with no class name before the words, and that line is now the default for every server, the test entries included.
  • Any other failure to start reads as before. StartupError keeps the failure it wraps as its cause, which is how the notice finds the refusal. Colour and link codes follow whether stderr is a terminal.

What the terminal shows:

  ✖ Auto Runtime could not start

  The ledger is kept in the file /Users/ada/.auto-runtime/ledger.db, and was
  made by another version of Auto Runtime. This version keeps secrets in a
  different shape and cannot read the secrets this ledger holds.

  What you can do
    Delete the ledger and start Auto Runtime again. Everything in the ledger
    goes with it, every playbook, definition, run and connection among it.

      rm -f /Users/ada/.auto-runtime/ledger.db /Users/ada/.auto-runtime/ledger.db-wal /Users/ada/.auto-runtime/ledger.db-shm

  Need a hand? Ask us on Discord: https://discord.gg/B8BKcKMRm8

  kept_secrets has the columns held, id, kept_at, kept_by, version, where
  this version keeps claimed_until, ends_with, held, id, kept_at, kept_by,
  kid, version, wrapped_key.

Tests

  • The ledger's secrets behaviour checks the refusal's type and fields.
  • ledger-of-another-version.test.ts covers the words for a file, a relative path, PostgreSQL and the image, and runs the delete command in a real folder whose name holds a space, a quote and a $.
  • failure-notice.test.ts checks the terminal notice line by line, with and without colours.
  • ledger-database.test.ts checks that the layer turns the refusal into the server's error and passes any other failure through unchanged.
  • run-server.test.ts, ledger-startup.test.ts and terminal-control.test.ts start a real server and a real auto-runtime on a ledger of another version and read what each prints, including stderr sent to a file.

Checklist

  • The PR title is a conventional commit with a workspace scope, such as feat(reasoning): .... It becomes the squash commit and the changelog entry.
  • pnpm check passes locally, with every file at 100% coverage.
  • I've signed the Contributor License Agreement (the CLA bot asks on your first PR).

… and where to ask

A runtime that opened a ledger whose tables another version had made
stopped with the ledger's own sentence, wrapped twice, which said to
delete "the local database" without saying where it was, so a person
who ran npx in an empty folder could not find the file, and a ledger in
PostgreSQL was told to delete a local database it did not have. The
ledger now refuses such a table as a LedgerShapeRefused that names the
table, what it holds and the columns found and kept, and the server,
which knows where its ledger is kept, answers it in words of its own:
where the ledger is, that this version does not yet carry a ledger over
from one version to the next, what to do, and where to ask, on Discord.

Started in a terminal, the runtime shows this as a notice of its own
beneath the logo, as it shows the one that it is ready: what happened,
then "What you can do" with the command that deletes the ledger file
and the two SQLite keeps beside it, then the Discord invite, then the
columns, dimmed. A ledger in PostgreSQL is told to point DATABASE_URL
at an empty database instead, with no command. Started as a server,
the runtime says the same in its one line on stderr, ending with the
command, so nothing follows it when it is copied. Any other failure to
start reads as before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@rami-hatoum
rami-hatoum force-pushed the fix/ledger-shape-notice branch from bcfe743 to 6142bb7 Compare October 21, 2026 11:00
…y shell and says what holds

The command that deletes a ledger file names the file, its -wal and its -shm one by one, each
quoted for the shell, so it deletes the three files in every POSIX shell; the brace expansion,
which a POSIX sh leaves as it is, is gone. Where RUNTIME_DISTRIBUTION is docker, the container
has stopped, so the notice gives words instead: delete the three files from the volume mounted
at /data when the ledger is in the image's folder /app/data, or from the volume that holds the
ledger's folder anywhere else, or remove the volume. The settings read RUNTIME_DISTRIBUTION even
when the usage ping is turned off.

A server that stops on such a ledger says on its single line of stderr "Auto Runtime could not
start:" and the refusal's own words, with no error names before them. This is the line every
server prints unless it is given a notice of its own; every other failure prints as before.

The words say only what is true of the refused table: this version keeps secrets, or recorded
content, in a different shape and cannot read those the ledger holds. They no longer say that a
ledger is not yet carried over from one version to the next, and they no longer offer help to
keep a ledger, which the runtime cannot give; deleting the ledger, they say, takes everything
in it, every playbook, definition, run and connection among it.

One function says where the ledger is kept, for the start log and for the refusal, so the
refusal reads "The ledger is kept in the file ..." as the log does, and the log's words are
unchanged. The invite sits beside the other links in local-banner.ts, the test fixture is
a-ledger-of-another-version.ts, and the terminal notice takes its colors and links from stderr,
the stream it is written to, so a notice sent to a file holds no escape code.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@rami-hatoum
rami-hatoum force-pushed the fix/ledger-shape-notice branch from 6142bb7 to b44ff4c Compare October 21, 2026 11:06
@rami-hatoum
rami-hatoum merged commit 168a756 into main Oct 21, 2026
20 checks passed
@rami-hatoum
rami-hatoum deleted the fix/ledger-shape-notice branch October 21, 2026 11:15
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.

2 participants