[FIXED] App Server shema migration treats 'client_hidden: false' as DELETE_COLUMN / ADD_COLUMN on existing Users table columns

Hello Anvil team,
I’m working on Anvil for few years now and really appreciate this tool !

I would like to report what looks like to me a potentially dangerous App Server schema migration issue related to the new “client_hidden” metadata on Data Table columns.

Context

I’m running an Anvil app on a Pi5 server at work, for over a year, using:

  • Anvil App Server

  • PostgreSQL data base

  • Docker Swarm

  • A self-hosted production app

  • A standard Anvil Users table used for login/password authentication

The app is deployed from a Git repository. The app folder is mounted into an App Server container.

Before the issue, my App Server config had:


auto-migrate: true

The problem came up after the new implementation of the “client visible” data columns:
After a normal app update from Git, users could no longer log in with their existing passwords. They had to use “forgot password” to regain access.

What I noticed:

The App Server automatically applied a migration that included this:


Data tables schema out of date. Applying migrations:

({:type :DELETE_COLUMN, :table "users", :column_name "password_hash"}

 {:type :DELETE_COLUMN, :table "users", :column_name "centre"}

 ...

[INFO anvil.app-server.tables] Migrating automatically...

[INFO anvil.app-server.tables] Migration complete.

This caused existing user passwords to stop working, because the users.password_hash column was deleted and recreated.

After using “forgot password”, login worked again, because a new password hash was written into the new password_hash column.

The PostgreSQL table physically contained the expected columns:


password_hash   text

accept_data     boolean

centre          bigint

So the PG SQL columns were not missing.

But the relevant part of anvil.yaml contained these columns with explicit client_hidden: false metadata:


users:

  client: search

  columns:

    - admin_ui: {order: 3, width: 138}

      client_hidden: false

      name: password_hash

      type: string



    - admin_ui: {order: 22, width: 200}

      client_hidden: false

      name: accept_data

      type: bool



    - admin_ui: {order: 22.5, width: 200}

      client_hidden: false

      name: centre

      target: lieux

      type: link_single

With this YAML, App Server reported the following proposed migration:


Data tables schema out of date. Here is the migration that will run if you restart Anvil with the --auto-migrate command-line flag:

({:type :DELETE_COLUMN, :table "users", :column_name "accept_data"}

 {:type :DELETE_COLUMN, :table "users", :column_name "password_hash"}

 {:type :DELETE_COLUMN, :table "users", :column_name "centre"}

 {:type :ADD_COLUMN,

  :table "users",

  :column

  {:admin_ui {:order 3, :width 138},

   :client_hidden false,

   :name "password_hash",

   :type "string"}}

 {:type :ADD_COLUMN,

  :table "users",

  :column

  {:admin_ui {:order 22, :width 200},

   :client_hidden false,

   :name "accept_data",

   :type "bool"}}

 {:type :ADD_COLUMN,

  :table "users",

  :column

  {:admin_ui {:order 22.5, :width 200},

   :client_hidden false,

   :name "centre",

   :target "lieux",

   :type "link_single"}})

This is the dangerous part: App Server appears to treat the explicit client_hidden: false metadata as a schema difference requiring DELETE_COLUMN and ADD_COLUMN, instead of treating it as a metadata-only change.

What I tried: (and it worked)

When I removed the explicit client_hidden: false lines from anvil.yaml, leaving the columns like this:


- admin_ui: {order: 3, width: 138}

  name: password_hash

  type: string



- admin_ui: {order: 22, width: 200}

  name: accept_data

  type: bool



- admin_ui: {order: 22.5, width: 200}

  name: centre

  target: lieux

  type: link_single

the App Server started normally and reported:


Running Anvil Database Migrator for (base data-tables runtime) DB.

Database is already up to date at version '2025-06-09-recreate-table-views'

[INFO anvil.core.server] HTTP Server running on port 80

So removing the explicit client_hidden: false metadata made the schema match again.

Does it seem like a bug ?

A change such as:


client_hidden: false

on an existing column should not result in:


DELETE_COLUMN users.password_hash

ADD_COLUMN users.password_hash

Especially on the Users table, this is dangerous because deleting and recreating password_hash invalidates all existing user passwords.

In my case, because `auto-migrate: (“true” was enabled), the destructive migration was applied automatically in production.

Current workaround

I have now changed my production config to:


auto-migrate: false

I temporarily used:


ignore-invalid-schema: true

to restart the app without applying the destructive migration.

Then I restored PostgreSQL from a backup and removed the explicit client_hidden: false lines from anvil.yaml. After that, the App Server considered the database schema up to date again.

Should really App Server generate DELETE_COLUMN / ADD_COLUMN for an existing column only because “client_hidden: false” appears explicitly in anvil.yaml file ?

At minimum, should App Server not suggest or automatically apply destructive migrations on sensitive Users table columns such as:


users.password_hash

when the SQL column already exists and only metadata differs.

Actual behavior

App Server proposed and, with auto-migrate: true, applied:


DELETE_COLUMN users.password_hash

ADD_COLUMN users.password_hash

This invalidated existing user passwords.

Impact

This is a serious production risk for self-hosted App Server users, especially those using:


auto-migrate: true

because it can silently destroy users.password_hash and force all users to reset their passwords.

Could you please confirm whether this is expected behavior or a migration bug related to the new client_hidden column metadata?

Again, thank you very much for your work !

Ouch! Yes, I’m going to call this a bug report (moved to the appropriate forum!)

We’ll get a new version of the App Server out with a fix!

1 Like

Anvil App Server 1.16.0 is now available.

The release fixes the schema migration issue you faced.

Thank you very much stucork for your reactivity !
I use this opportunity to express my deep appreciation for the work done by you and the whole Anvil team !

1 Like