Failing to import new umanaged host on 1.17.1, fact name/value association broken?

I’ve got a very odd error going on here. It’s a new build of Foreman (1.17.1, using the ARM64 DEB packages), and Salt (no Puppet or Installer, I built the Apache/DB/Settings config by hand, if it matters).

When I try to import the host itself using the ENC in the Salt package, I get this:

$ foreman-node `hostname -f`
2018-06-20T20:38:32 2af562a0 [app] [D] Merging facts for 'quartz.elysium.emeraldreverie.org': added 123 facts
2018-06-20T20:38:32 2af562a0 [sql] [D]    (1.6ms)  COMMIT
2018-06-20T20:38:32 2af562a0 [app] [I] Import facts for 'quartz.elysium.emeraldreverie.org' completed. Added: 123, Updated: 0, Deleted 0 facts
2018-06-20T20:38:32 2af562a0 [sql] [D]    (1.0ms)  BEGIN
2018-06-20T20:38:32 2af562a0 [sql] [D]   Setting Load (2.4ms)  SELECT  "settings".* FROM "settings" WHERE "settings"."name" = $1 ORDER BY "settings"."name" ASC LIMIT $2  [["name", "root_pass"], ["LIMIT", 1]]
2018-06-20T20:38:32 2af562a0 [sql] [D]   SQL (5.6ms)  INSERT INTO "hosts" ("name", "updated_at", "created_at", "type", "lookup_value_matcher") VALUES ($1, $2, $3, $4, $5) RETURNING "id"  [["name", "quartz.elysium.emeraldreverie.org"], ["updated_at", "2018-06-20 20:38:32.849191"], ["created_at", "2018-06-20 20:38:32.849191"], ["type", "Host::Managed"], ["lookup_value_matcher", "fqdn=quartz.elysium.emeraldreverie.org"]]
2018-06-20T20:38:32 2af562a0 [sql] [D]   FactValue Exists (1.7ms)  SELECT  1 AS one FROM "fact_values" WHERE "fact_values"."fact_name_id" IS NULL AND "fact_values"."host_id" = $1 LIMIT $2  [["host_id", 14], ["LIMIT", 1]]
2018-06-20T20:38:32 2af562a0 [sql] [D]   SQL (4.5ms)  INSERT INTO "fact_values" ("value", "host_id", "updated_at", "created_at") VALUES ($1, $2, $3, $4) RETURNING "id"  [["value", "Linux"], ["host_id", 14], ["updated_at", "2018-06-20 20:38:32.884372"], ["created_at", "2018-06-20 20:38:32.884372"]]
2018-06-20T20:38:32 2af562a0 [app] [W] Rolling back due to exception during save
 | ActiveRecord::NotNullViolation: PG::NotNullViolation: ERROR:  null value in column "fact_name_id" violates not-null constraint
 | DETAIL:  Failing row contains (14, Linux, null, 14, 2018-06-20 20:38:32.884372, 2018-06-20 20:38:32.884372).
 | : INSERT INTO "fact_values" ("value", "host_id", "updated_at", "created_at") VALUES ($1, $2, $3, $4) RETURNING "id"
 | /usr/share/foreman/vendor/ruby/2.3.0/gems/activerecord-5.1.4/lib/active_record/connection_adapters/postgresql_adapter.rb:614:in `async_exec'
 | /usr/share/foreman/vendor/ruby/2.3.0/gems/activerecord-5.1.4/lib/active_record/connection_adapters/postgresql_adapter.rb:614:in `block (2 levels) in exec_no_cache'
 | /usr/share/foreman/vendor/ruby/2.3.0/gems/activesupport-5.1.4/lib/active_support/dependencies/interlock.rb:46:in `block in permit_concurrent_loads'
 | /usr/share/foreman/vendor/ruby/2.3.0/gems/activesupport-5.1.4/lib/active_support/concurrency/share_lock.rb:185:in `yield_shares'
 | /usr/share/foreman/vendor/ruby/2.3.0/gems/activesupport-5.1.4/lib/active_support/dependencies/interlock.rb:45:in `permit_concurrent_loads'
 | /usr/share/foreman/vendor/ruby/2.3.0/gems/activerecord-5.1.4/lib/active_record/connection_adapters/postgresql_adapter.rb:613:in `block in exec_no_cache'
 | /usr/share/foreman/vendor/ruby/2.3.0/gems/activerecord-5.1.4/lib/active_record/connection_adapters/abstract_adapter.rb:612:in `block (2 levels) in log'
 | /usr/lib/ruby/2.3.0/monitor.rb:214:in `mon_synchronize'
 | /usr/share/foreman/vendor/ruby/2.3.0/gems/activerecord-5.1.4/lib/active_record/connection_adapters/abstract_adapter.rb:611:in `block in log'
 | /usr/share/foreman/vendor/ruby/2.3.0/gems/activesupport-5.1.4/lib/active_support/notifications/instrumenter.rb:21:in `instrument'
 | /usr/share/foreman/vendor/ruby/2.3.0/gems/activerecord-5.1.4/lib/active_record/connection_adapters/abstract_adapter.rb:603:in `log'
 | /usr/share/foreman/vendor/ruby/2.3.0/gems/activerecord-5.1.4/lib/active_record/connection_adapters/postgresql_adapter.rb:612:in `exec_no_cache'
 | /usr/share/foreman/vendor/ruby/2.3.0/gems/activerecord-5.1.4/lib/active_record/connection_adapters/postgresql_adapter.rb:601:in `execute_and_clear'
 | /usr/share/foreman/vendor/ruby/2.3.0/gems/activerecord-5.1.4/lib/active_record/connection_adapters/postgresql/database_statements.rb:79:in `exec_query'
 | /usr/share/foreman/vendor/ruby/2.3.0/gems/activerecord-5.1.4/lib/active_record/connection_adapters/abstract/database_statements.rb:102:in `exec_insert'
 | /usr/share/foreman/vendor/ruby/2.3.0/gems/activerecord-5.1.4/lib/active_record/connection_adapters/postgresql/database_statements.rb:113:in `exec_insert'
 | /usr/share/foreman/vendor/ruby/2.3.0/gems/activerecord-5.1.4/lib/active_record/connection_adapters/abstract/database_statements.rb:133:in `insert'
 | /usr/share/foreman/vendor/ruby/2.3.0/gems/activerecord-5.1.4/lib/active_record/connection_adapters/abstract/query_cache.rb:17:in `insert'
 | /usr/share/foreman/vendor/ruby/2.3.0/gems/activerecord-5.1.4/lib/active_record/relation.rb:61:in `insert'
 | /usr/share/foreman/vendor/ruby/2.3.0/gems/activerecord-5.1.4/lib/active_record/persistence.rb:589:in `_create_record'
 | /usr/share/foreman/vendor/ruby/2.3.0/gems/activerecord-5.1.4/lib/active_record/counter_cache.rb:178:in `_create_record'
 | /usr/share/foreman/vendor/ruby/2.3.0/gems/activerecord-5.1.4/lib/active_record/locking/optimistic.rb:76:in `_create_record'
 | /usr/share/foreman/vendor/ruby/2.3.0/gems/activerecord-5.1.4/lib/active_record/attribute_methods/dirty.rb:296:in `_create_record'
 | /usr/share/foreman/vendor/ruby/2.3.0/gems/activerecord-5.1.4/lib/active_record/callbacks.rb:340:in `block in _create_record'
 | /usr/share/foreman/vendor/ruby/2.3.0/gems/activesupport-5.1.4/lib/active_support/callbacks.rb:131:in `run_callbacks'
 | /usr/share/foreman/vendor/ruby/2.3.0/gems/activesupport-5.1.4/lib/active_support/callbacks.rb:827:in `_run_create_callbacks'
 | /usr/share/foreman/vendor/ruby/2.3.0/gems/activerecord-5.1.4/lib/active_record/callbacks.rb:340:in `_create_record'
 | /usr/share/foreman/vendor/ruby/2.3.0/gems/activerecord-5.1.4/lib/active_record/timestamp.rb:95:in `_create_record'
 | /usr/share/foreman/vendor/ruby/2.3.0/gems/activerecord-5.1.4/lib/active_record/persistence.rb:563:in `create_or_update'
 | /usr/share/foreman/vendor/ruby/2.3.0/gems/activerecord-5.1.4/lib/active_record/callbacks.rb:336:in `block in create_or_update'
 | /usr/share/foreman/vendor/ruby/2.3.0/gems/activesupport-5.1.4/lib/active_support/callbacks.rb:131:in `run_callbacks'
 | /usr/share/foreman/vendor/ruby/2.3.0/gems/activesupport-5.1.4/lib/active_support/callbacks.rb:827:in `_run_save_callbacks'
 | /usr/share/foreman/vendor/ruby/2.3.0/gems/activerecord-5.1.4/lib/active_record/callbacks.rb:336:in `create_or_update'
 | /usr/share/foreman/vendor/ruby/2.3.0/gems/activerecord-5.1.4/lib/active_record/persistence.rb:129:in `save'
 | /usr/share/foreman/vendor/ruby/2.3.0/gems/activerecord-5.1.4/lib/active_record/validations.rb:44:in `save'
 | /usr/share/foreman/vendor/ruby/2.3.0/gems/activerecord-5.1.4/lib/active_record/attribute_methods/dirty.rb:35:in `save'
 | /usr/share/foreman/vendor/ruby/2.3.0/gems/activerecord-5.1.4/lib/active_record/transactions.rb:308:in `block (2 levels) in save'
 | /usr/share/foreman/vendor/ruby/2.3.0/gems/activerecord-5.1.4/lib/active_record/transactions.rb:384:in `block in with_transaction_returning_status'
 | /usr/share/foreman/vendor/ruby/2.3.0/gems/activerecord-5.1.4/lib/active_record/connection_adapters/abstract/database_statements.rb:233:in `transaction'
 | /usr/share/foreman/vendor/ruby/2.3.0/gems/activerecord-5.1.4/lib/active_record/transactions.rb:210:in `transaction'
 | /usr/share/foreman/vendor/ruby/2.3.0/gems/activerecord-5.1.4/lib/active_record/transactions.rb:381:in `with_transaction_returning_status'
 | /usr/share/foreman/vendor/ruby/2.3.0/gems/activerecord-5.1.4/lib/active_record/transactions.rb:308:in `block in save'
 | /usr/share/foreman/vendor/ruby/2.3.0/gems/activerecord-5.1.4/lib/active_record/transactions.rb:323:in `rollback_active_record_state!'
 | /usr/share/foreman/vendor/ruby/2.3.0/gems/activerecord-5.1.4/lib/active_record/transactions.rb:307:in `save'
 | /usr/share/foreman/vendor/ruby/2.3.0/gems/activerecord-5.1.4/lib/active_record/suppressor.rb:42:in `save'
 | /usr/share/foreman/vendor/ruby/2.3.0/gems/activerecord-5.1.4/lib/active_record/associations/collection_association.rb:371:in `insert_record'
 | /usr/share/foreman/vendor/ruby/2.3.0/gems/activerecord-5.1.4/lib/active_record/associations/has_many_association.rb:34:in `insert_record'
 | /usr/share/foreman/vendor/ruby/2.3.0/gems/activerecord-5.1.4/lib/active_record/autosave_association.rb:410:in `block in save_collection_association'
 | /usr/share/foreman/vendor/ruby/2.3.0/gems/activerecord-5.1.4/lib/active_record/autosave_association.rb:401:in `each'
 | /usr/share/foreman/vendor/ruby/2.3.0/gems/activerecord-5.1.4/lib/active_record/autosave_association.rb:401:in `save_collection_association'
 | /usr/share/foreman/vendor/ruby/2.3.0/gems/activerecord-5.1.4/lib/active_record/autosave_association.rb:186:in `block in add_autosave_association_callbacks'
 | /usr/share/foreman/vendor/ruby/2.3.0/gems/activerecord-5.1.4/lib/active_record/autosave_association.rb:158:in `instance_eval'
 | /usr/share/foreman/vendor/ruby/2.3.0/gems/activerecord-5.1.4/lib/active_record/autosave_association.rb:158:in `block in define_non_cyclic_method'
 | /usr/share/foreman/vendor/ruby/2.3.0/gems/activesupport-5.1.4/lib/active_support/callbacks.rb:413:in `block in make_lambda'
 | /usr/share/foreman/vendor/ruby/2.3.0/gems/activesupport-5.1.4/lib/active_support/callbacks.rb:235:in `block in halting_and_conditional'
 | /usr/share/foreman/vendor/ruby/2.3.0/gems/activesupport-5.1.4/lib/active_support/callbacks.rb:511:in `block in invoke_after'
 | /usr/share/foreman/vendor/ruby/2.3.0/gems/activesupport-5.1.4/lib/active_support/callbacks.rb:511:in `each'
 | /usr/share/foreman/vendor/ruby/2.3.0/gems/activesupport-5.1.4/lib/active_support/callbacks.rb:511:in `invoke_after'
 | /usr/share/foreman/vendor/ruby/2.3.0/gems/activesupport-5.1.4/lib/active_support/callbacks.rb:132:in `run_callbacks'
 | /usr/share/foreman/vendor/ruby/2.3.0/gems/activesupport-5.1.4/lib/active_support/callbacks.rb:827:in `_run_create_callbacks'
 | /usr/share/foreman/vendor/ruby/2.3.0/gems/activerecord-5.1.4/lib/active_record/callbacks.rb:340:in `_create_record'
 | /usr/share/foreman/vendor/ruby/2.3.0/gems/activerecord-5.1.4/lib/active_record/timestamp.rb:95:in `_create_record'
 | /usr/share/foreman/vendor/ruby/2.3.0/gems/activerecord-5.1.4/lib/active_record/persistence.rb:563:in `create_or_update'
 | /usr/share/foreman/vendor/ruby/2.3.0/gems/activerecord-5.1.4/lib/active_record/callbacks.rb:336:in `block in create_or_update'
 | /usr/share/foreman/vendor/ruby/2.3.0/gems/activesupport-5.1.4/lib/active_support/callbacks.rb:108:in `block in run_callbacks'
 | /usr/share/foreman/app/models/concerns/orchestration.rb:47:in `around_save_orchestration'
 | /usr/share/foreman/vendor/ruby/2.3.0/gems/activesupport-5.1.4/lib/active_support/callbacks.rb:117:in `block in run_callbacks'
 | /usr/share/foreman/vendor/ruby/2.3.0/gems/activesupport-5.1.4/lib/active_support/callbacks.rb:135:in `run_callbacks'
 | /usr/share/foreman/vendor/ruby/2.3.0/gems/activesupport-5.1.4/lib/active_support/callbacks.rb:827:in `_run_save_callbacks'
 | /usr/share/foreman/vendor/ruby/2.3.0/gems/activerecord-5.1.4/lib/active_record/callbacks.rb:336:in `create_or_update'
 | /usr/share/foreman/vendor/ruby/2.3.0/gems/activerecord-5.1.4/lib/active_record/persistence.rb:129:in `save'
 | /usr/share/foreman/vendor/ruby/2.3.0/gems/activerecord-5.1.4/lib/active_record/validations.rb:44:in `save'
 | /usr/share/foreman/vendor/ruby/2.3.0/gems/activerecord-5.1.4/lib/active_record/attribute_methods/dirty.rb:35:in `save'
 | /usr/share/foreman/vendor/ruby/2.3.0/gems/activerecord-5.1.4/lib/active_record/transactions.rb:308:in `block (2 levels) in save'
 | /usr/share/foreman/vendor/ruby/2.3.0/gems/activerecord-5.1.4/lib/active_record/transactions.rb:384:in `block in with_transaction_returning_status'
 | /usr/share/foreman/vendor/ruby/2.3.0/gems/activerecord-5.1.4/lib/active_record/connection_adapters/abstract/database_statements.rb:235:in `block in transaction'
 | /usr/share/foreman/vendor/ruby/2.3.0/gems/activerecord-5.1.4/lib/active_record/connection_adapters/abstract/transaction.rb:194:in `block in within_new_transaction'
 | /usr/lib/ruby/2.3.0/monitor.rb:214:in `mon_synchronize'
 | /usr/share/foreman/vendor/ruby/2.3.0/gems/activerecord-5.1.4/lib/active_record/connection_adapters/abstract/transaction.rb:191:in `within_new_transaction'
 | /usr/share/foreman/vendor/ruby/2.3.0/gems/activerecord-5.1.4/lib/active_record/connection_adapters/abstract/database_statements.rb:235:in `transaction'
 | /usr/share/foreman/vendor/ruby/2.3.0/gems/activerecord-5.1.4/lib/active_record/transactions.rb:210:in `transaction'
 | /usr/share/foreman/vendor/ruby/2.3.0/gems/activerecord-5.1.4/lib/active_record/transactions.rb:381:in `with_transaction_returning_status'
 | /usr/share/foreman/vendor/ruby/2.3.0/gems/activerecord-5.1.4/lib/active_record/transactions.rb:308:in `block in save'
 | /usr/share/foreman/vendor/ruby/2.3.0/gems/activerecord-5.1.4/lib/active_record/transactions.rb:323:in `rollback_active_record_state!'
 | /usr/share/foreman/vendor/ruby/2.3.0/gems/activerecord-5.1.4/lib/active_record/transactions.rb:307:in `save'
 | /usr/share/foreman/vendor/ruby/2.3.0/gems/activerecord-5.1.4/lib/active_record/suppressor.rb:42:in `save'
 | /usr/share/foreman/app/models/concerns/foreman/sti.rb:26:in `save'
 | /usr/share/foreman/app/models/host/base.rb:145:in `import_facts'
 | /usr/share/foreman/app/models/host/managed.rb:298:in `import_facts'
 | /usr/share/foreman/app/controllers/api/v2/hosts_controller.rb:286:in `facts'

I’ve snipped the top of the logs, basically it fails here on the save call, after importer.import! has finished. Note that this is in the core code rather than the Salt plugin, but I’m not 100% sure if that means the error isn’t with Salt.

What’s very odd is this line:

INSERT INTO "fact_values" ("value", "host_id", "updated_at", "created_at") VALUES ($1, $2, $3, $4) RETURNING "id"

This appears to show that it’s not even trying to pass in fact_name_id when saving. It’s bombing on the first fact in the hash (I’ve confirmed by deleting that fact and it immediately bombs on the next one) so it doesn’t seem related to the value.

I had a look at models/host/base.rb and the fact name/value models and they haven’t changed in ages, so what am I missing?

Quick bump, this is happening across multiple hosts (different OS, different Salt version on the client), so it’s not some weirdness in the facts, I don’t think. Any ideas?