semaphoreui/semaphore · error

failed to import

Error message

failed to import %s: %s

What it means

The import runner wraps each exporter's restore() failure with the failing type name, producing 'failed to import <type>: <cause>'. Like the export counterpart, the actionable information is the inner cause (missing key mappings, constraint violations, etc.).

Solutions

  1. Inspect the inner error after 'failed to import <type>:' and address that root cause
  2. Check exporter.getErrors() for per-entity problems reported during the same run
  3. Ensure the target database is compatible (version/schema) with the export file, then retry the import
Defensive patterns

Strategy: try-catch

Validate before calling

// pre-flight: verify referential completeness of the export file
for _, ref := range exportRefs {
    if !targetStore.Exists(ref.Type, ref.Key) {
        return fmt.Errorf("import would fail: missing %s %s", ref.Type, ref.Key)
    }
}

Try / catch

err := chain.Restore(store)
if err != nil {
    if strings.HasPrefix(err.Error(), "failed to import ") {
        cause := strings.SplitN(err.Error(), ": ", 2)[1]
        log.Errorf("import failed, root cause: %s", cause)
    }
    return err
}

Prevention

When it happens

Trigger: During Import/Restore(), exporter.restore(store, p, progress) returns an error for type `name`; the chain stops and returns the wrapped message (afterwards also counting exporter.getErrors()).

Common situations: Importing into a database with conflicting/missing referenced entities ('key not found'); schema differences between source and target Semaphore versions; unique-constraint collisions on insert.

Related errors


AI-assisted analysis of semaphoreui/semaphore@1774ccb71a (2026-09-07). Data as JSON: /api/errors/e5ea1039c2ff24dd. Report an issue: GitHub.

Appendix: source

Thrown at services/export/Exporter.go:529

	for _, name := range keys {

		progress := &ProgressBar{printer: func(progress float32, count int64) {
			strLen := len(name)
			if progress == 1 {
				spaces := fmt.Sprintf("%*s", 50-strLen-len(strconv.FormatInt(count, 10)), " ")
				fmt.Printf("\rImported %s%s %d", name, spaces, count)
			} else {
				spaces := fmt.Sprintf("%*s", 45-strLen, " ")
				fmt.Printf("\rImporting %s%s %d%%", name, spaces, int(progress*100))
			}
		}, progress: 0}

		progress.updateForce(0, 0)
		exporter := p.exporters[name]
		err := exporter.restore(store, p, progress)
		if err != nil {
			fmt.Println()
			return fmt.Errorf("failed to import %s: %s", name, err.Error())
		}
		progress.updateForce(1, progress.count)
		fmt.Println()

		errCount := len(exporter.getErrors())
		if errCount > 0 {
			fmt.Printf("    Errors: %d\n", errCount)

			if errLogSize > 0 {
				for i, err := range exporter.getErrors() {
					if i > errLogSize {
						break
					}
					fmt.Println("      ", err)
				}
			}
		}
		exporter.clear()

View on GitHub (pinned to 1774ccb71a)