Skip to content

[Bug] Environment weather fetch cannot persist rows because Prisma enum name does not match migrated PostgreSQL type #646

Description

@lutzkind

Summary

The Environment module can show a valid configured home location but remain permanently at 0 days recorded because every environment-fetch job fails when Prisma tries to write the source enum.

The database migration creates the PostgreSQL enum as:

public.environment_location_source

but the Prisma schema declares EnvironmentLocationSource without an enum @@map, so the Prisma 7 PostgreSQL driver adapter generates a cast/reference to:

public.EnvironmentLocationSource

That type does not exist. The fetch succeeds far enough to reach the database upsert, then the entire transaction fails and no environment_contexts rows are stored.

Affected version

Confirmed on a self-hosted server running:

  • HealthLog v1.32.31
  • Prisma client 7.8.0
  • PostgreSQL 16

Current main still has the same unmapped enum declaration, so this is not limited to the deployed patch version.

User-visible reproduction

  1. Enable/open the Environment module.
  2. Configure a valid home location and effective date.
  3. Wait for the immediate/default fetch or the nightly environment job.
  4. Open the native Environment screen.

Actual behavior

The screen shows:

Home location
<configured location>

Weather data
0 days recorded

No weather data ever appears.

Expected behavior

Recent eligible days should be fetched from Open-Meteo, persisted in environment_contexts, and reflected in the overview count and downstream environmental correlations.

Confirmed production evidence

The account had:

  • a valid coarse home latitude/longitude;
  • an IANA home timezone;
  • homeSince set to 20 July 2026;
  • the Environment module enabled by the normal default-on module policy.

Read-only database queries showed:

environment_contexts rows: 0
environment_travel_locations rows: 0

The overview endpoint correctly returned context_days = 0; this is not an iOS-only display error.

The nightly pg-boss job ran at the documented 02:10 Europe/Berlin schedule and retried three times. Each attempt failed with PostgreSQL error 42704:

[pg-boss] [environment-fetch] failed Error [DriverAdapterError]:
type "public.EnvironmentLocationSource" does not exist

The repeated failure occurred before any row could be committed.

Migration/schema mismatch

Migration 0217_v125_environmental_context creates:

CREATE TYPE "environment_location_source" AS ENUM ('HOME', 'TRAVEL');

Migration 0219_v125_env_home_since later adds:

ALTER TYPE "environment_location_source" ADD VALUE IF NOT EXISTS 'DEVICE';

The applied production database therefore contains:

public.environment_location_source
  HOME
  TRAVEL
  DEVICE

and environment_contexts.source uses that exact type.

Current prisma/schema.prisma declares:

enum EnvironmentLocationSource {
  HOME
  TRAVEL
  DEVICE
}

with no mapping to the migrated snake-case PostgreSQL type.

The EnvironmentContext model itself is correctly mapped to environment_contexts, but its enum is not.

Root cause

A schema/migration naming drift:

  • physical PostgreSQL enum: environment_location_source
  • logical Prisma enum: EnvironmentLocationSource
  • missing Prisma enum mapping

With the current Prisma PostgreSQL adapter, the upsert references the logical enum type name and PostgreSQL rejects it because only the snake-case type exists.

Smallest general fix

Map the Prisma enum to the existing database type and regenerate the client:

enum EnvironmentLocationSource {
  HOME
  TRAVEL
  DEVICE

  @@map("environment_location_source")
}

This preserves existing databases and future installs without renaming a live enum type or rewriting the column.

An alternative would be a migration that renames the physical PostgreSQL enum to "EnvironmentLocationSource", but mapping Prisma to the already-established snake-case database contract is smaller and less disruptive.

Recovery behavior

After the schema/client fix is deployed:

  • the existing nightly seven-day lookback should automatically retry and fill recent eligible dates;
  • an explicit backfill should work for the permitted range;
  • no manual deletion or recreation of the home location should be necessary.

Regression tests

Migrated-database integration

Create a real PostgreSQL test database by applying the production migrations, then run an EnvironmentContext create/upsert using each source value:

  • HOME
  • TRAVEL
  • DEVICE

This must be a database integration test, not only a mocked Prisma test, because mocks cannot detect physical enum-name drift.

Environment job

  • Configure a home location with an eligible effective date.
  • Stub Open-Meteo with one or more daily observations.
  • Run handleEnvironmentFetch().
  • Assert stored > 0 and rows exist in environment_contexts.
  • Re-run and verify idempotent upsert behavior.

API/UI

  • GET /api/environment reports the stored day count and latest date.
  • Native/web environment surfaces stop showing 0 days recorded after successful storage.

Migration-contract guard

Add a schema/migration consistency check for mapped PostgreSQL enums so a Prisma logical enum name cannot silently drift from its physical database type again.

Scope

This is not caused by Open-Meteo availability, the home effective-date rule, module configuration, or the native UI. The upstream fetch reaches the persistence path; the PostgreSQL enum lookup fails during the database write.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions