From 3e827fbb9203f79944d9456eb59e507f2ab54cab Mon Sep 17 00:00:00 2001 From: Oliver Kieselbach Date: Mon, 29 Jun 2026 18:53:39 +0200 Subject: [PATCH] fix(delegated): tenant-template membership write failed (Edm.DateTime out of range) AddTenantToTemplate returned 500 on the first add: the membership-row write threw because TenantTemplateEntity.CreatedDate was left at default(DateTime) (0001-01-01), which is below Azure Table Storage's Edm.DateTime minimum (1601). The meta row wrote fine only because Create stamps CreatedDate=UtcNow. Make CreatedDate nullable so membership rows omit it (null is valid); meta rows still carry it. Read-back maps null -> default. Confirmed via storage: the affected partition had only the meta row, no membership row. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../DataAccess/TableStorage/TableAdminRepository.cs | 2 +- .../Services/DelegatedAdminService.cs | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/Backend/AutopilotMonitor.Functions/DataAccess/TableStorage/TableAdminRepository.cs b/src/Backend/AutopilotMonitor.Functions/DataAccess/TableStorage/TableAdminRepository.cs index c5075bc2..8c9c2527 100644 --- a/src/Backend/AutopilotMonitor.Functions/DataAccess/TableStorage/TableAdminRepository.cs +++ b/src/Backend/AutopilotMonitor.Functions/DataAccess/TableStorage/TableAdminRepository.cs @@ -828,7 +828,7 @@ namespace AutopilotMonitor.Functions.DataAccess.TableStorage { template.Name = entity.Name; template.CreatedBy = entity.CreatedBy; - template.CreatedAt = entity.CreatedDate; + template.CreatedAt = entity.CreatedDate ?? default; return true; } diff --git a/src/Backend/AutopilotMonitor.Functions/Services/DelegatedAdminService.cs b/src/Backend/AutopilotMonitor.Functions/Services/DelegatedAdminService.cs index bf170ec9..f594b8fb 100644 --- a/src/Backend/AutopilotMonitor.Functions/Services/DelegatedAdminService.cs +++ b/src/Backend/AutopilotMonitor.Functions/Services/DelegatedAdminService.cs @@ -414,8 +414,12 @@ public class TenantTemplateEntity : ITableEntity /// UPN of the GlobalAdmin who created the template (meta row only). public string CreatedBy { get; set; } = string.Empty; - /// When the template was created (meta row only). - public DateTime CreatedDate { get; set; } + /// + /// When the template was created (meta row only). NULLABLE on purpose: membership rows leave it unset, and + /// Azure Table Storage rejects a default(DateTime) (0001-01-01) — below the Edm.DateTime minimum of 1601 — + /// which would make every membership-row write throw. A null DateTime? is simply omitted (valid). + /// + public DateTime? CreatedDate { get; set; } /// The managed tenant ID (lowercase) — denormalized copy of RowKey on membership rows; empty on meta. public string TenantId { get; set; } = string.Empty;