From 4cbd4c0c9e34be7ecff803c6674d89678def47c5 Mon Sep 17 00:00:00 2001 From: Astra Date: Mon, 14 Sep 2026 17:02:02 +0100 Subject: [PATCH] admin: fix env editor crash and ship .env.example into the image ReadEnvGroups returned (nil, nil) when .env.example wasn't found, and that nil slice marshaled to JSON null instead of []. The admin UI's env editor unconditionally calls .reduce()/.map() on the response, so it crashed on load with "Cannot read properties of null" -- and .env.example was never copied into the container image in the first place, so this was always the production code path, not an edge case. Fixed the nil-slice response and added .env.example to the image so the editor actually has a template of available settings to show. The real current values still require the deploy host to mount its actual .env file into the owpengram-admin container at /app/.env (procctl.Manager.Root is just os.Getwd(), i.e. the container's /app workdir) -- that's a systemd Quadlet unit change on the deploy host, not something this commit can fix on its own. Co-Authored-By: Claude Sonnet 5 --- Containerfile | 4 ++++ internal/procctl/procctl.go | 7 ++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/Containerfile b/Containerfile index 149dfe07..3e5b3549 100644 --- a/Containerfile +++ b/Containerfile @@ -28,5 +28,9 @@ COPY --from=build /out/telesrv-admin /app/telesrv-admin COPY --from=build /out/createuser /app/createuser COPY --from=build /src/data/langpack /app/data/langpack COPY --from=build /src/data/sticker-seed /app/data/sticker-seed +# telesrv-admin's Server Settings env editor (procctl.Manager.ReadEnvGroups) +# reads this as the template of available settings; without it the editor +# always reports zero groups. +COPY --from=build /src/.env.example /app/.env.example EXPOSE 2398 2600 ENTRYPOINT ["/app/gramsrv"] diff --git a/internal/procctl/procctl.go b/internal/procctl/procctl.go index d1cd85d6..60fd3c23 100644 --- a/internal/procctl/procctl.go +++ b/internal/procctl/procctl.go @@ -525,7 +525,12 @@ func (m *Manager) ReadEnvGroups() ([]EnvGroup, error) { tmplPath := filepath.Join(m.Root, ".env.example") tmplData, err := os.ReadFile(tmplPath) if os.IsNotExist(err) { - return nil, nil + // A nil slice here would marshal to JSON null instead of [] -- the + // admin UI's env editor unconditionally calls .reduce()/.map() on + // this response and crashes on null. .env.example isn't shipped + // inside the container image, so this path is the normal case in + // production, not an edge case. + return []EnvGroup{}, nil } if err != nil { return nil, fmt.Errorf("read .env.example: %w", err)