diff --git a/go-glx/gedcom_import_test.go b/go-glx/gedcom_import_test.go index b3d873d6..efd3a62d 100644 --- a/go-glx/gedcom_import_test.go +++ b/go-glx/gedcom_import_test.go @@ -1595,6 +1595,44 @@ func TestImportCensus_WithMedia(t *testing.T) { assert.True(t, mediaLinked, "census OBJE should be linked to source or citation") } +// TestImportMedia_EmptyFileSkipped tests that OBJE records with empty FILE +// values do not create media entities with empty URIs. Fixes #492. +func TestImportMedia_EmptyFileSkipped(t *testing.T) { + gedcom := `0 HEAD +1 GEDC +2 VERS 5.5.1 +0 @O1@ OBJE +1 FILE +1 TITL Empty file reference +0 @I1@ INDI +1 NAME Test /Person/ +0 TRLR` + + glxFile, _, err := ImportGEDCOM(strings.NewReader(gedcom), nil) + require.NoError(t, err) + + // Should NOT create a media entity with empty URI — the OBJE should be skipped entirely + assert.Empty(t, glxFile.Media, "OBJE with empty FILE should not create any media entity") +} + +// TestImportMedia_NoFileTagSkipped tests that OBJE records with no FILE tag +// at all do not create media entities. +func TestImportMedia_NoFileTagSkipped(t *testing.T) { + gedcom := `0 HEAD +1 GEDC +2 VERS 5.5.1 +0 @O1@ OBJE +1 TITL Photo with no file reference +0 @I1@ INDI +1 NAME Test /Person/ +0 TRLR` + + glxFile, _, err := ImportGEDCOM(strings.NewReader(gedcom), nil) + require.NoError(t, err) + + assert.Empty(t, glxFile.Media, "OBJE with no FILE tag should not create a media entity") +} + // TestImportFamilyCensus_SingleSpouse tests family census with only one spouse. func TestImportFamilyCensus_SingleSpouse(t *testing.T) { gedcom := `0 HEAD diff --git a/go-glx/gedcom_media.go b/go-glx/gedcom_media.go index 737bed9b..45b815c0 100644 --- a/go-glx/gedcom_media.go +++ b/go-glx/gedcom_media.go @@ -36,6 +36,14 @@ func convertMedia(objeRecord *GEDCOMRecord, conv *ConversionContext) error { // Convert using common logic media := convertMediaCommon(objeRecord, mediaID, conv) + // Skip media entities with empty URI — happens when OBJE has no FILE + // tag or an empty FILE value and no BLOB data. Fixes #492. + if media.URI == "" { + conv.Logger.LogInfof("Skipping OBJE %s: no FILE reference or BLOB data", objeRecord.XRef) + delete(conv.MediaIDMap, objeRecord.XRef) // clean up stale mapping + return nil + } + // Handle SOUR subrecords (only for top-level OBJE records) for _, sub := range objeRecord.SubRecords { if sub.Tag == GedcomTagSour { @@ -76,6 +84,12 @@ func convertEmbeddedMedia(objeRecord *GEDCOMRecord, conv *ConversionContext) str // Convert using common logic media := convertMediaCommon(objeRecord, mediaID, conv) + // Skip if no URI (empty FILE, no BLOB). Fixes #492. + if media.URI == "" { + conv.Logger.LogInfo("Skipping embedded OBJE: no FILE reference or BLOB data") + return "" + } + // Store media conv.GLX.Media[mediaID] = media conv.Stats.MediaCreated++