apache/answer · error

update tag failed: %w

Error message

update tag failed: %w

What it means

Wraps the xorm Update error when persisting a tag's recomputed question_count in the main branch of updateTagCount (tags that have available tag relations). The row UPDATE failed, the tag ID is logged, and the migration aborts.

Source

Thrown at internal/migrations/v13.go:245

		_, ok := tagCountMap[v.TagID]
		if !ok {
			tagCountMap[v.TagID] = 1
		} else {
			tagCountMap[v.TagID]++
		}
	}
	TagList := make([]entity.Tag, 0)
	err = x.Context(ctx).Find(&TagList, &entity.Tag{})
	if err != nil {
		return fmt.Errorf("get tag  failed: %w", err)
	}
	for _, tag := range TagList {
		_, ok := tagCountMap[tag.ID]
		if ok {
			tag.QuestionCount = tagCountMap[tag.ID]
			if _, err = x.Context(ctx).Update(tag, &entity.Tag{ID: tag.ID}); err != nil {
				log.Errorf("update %+v tag failed: %s", tag.ID, err)
				return fmt.Errorf("update tag failed: %w", err)
			}
		} else {
			tag.QuestionCount = 0
			if _, err = x.Context(ctx).Cols("question_count").Update(tag, &entity.Tag{ID: tag.ID}); err != nil {
				log.Errorf("update %+v tag failed: %s", tag.ID, err)
				return fmt.Errorf("update tag failed: %w", err)
			}
		}
	}
	return nil
}

// updateUserQuestionCount update user question count
func updateUserQuestionCount(ctx context.Context, x *xorm.Engine) error {
	questionList := make([]QuestionV13, 0)
	err := x.Context(ctx).Where(builder.Lt{"status": entity.QuestionStatusDeleted}).Find(&questionList, &QuestionV13{})
	if err != nil {
		return fmt.Errorf("get question  failed: %w", err)

View on GitHub (pinned to 3b9f137061)

Solutions

  1. Read the wrapped driver error to distinguish lock timeout from schema issues
  2. Verify the question_count column exists
  3. Re-run the migration; updates are idempotent
  4. Batch the updates or run during low-traffic windows to reduce lock contention

Example fix

// before
if _, err = x.Context(ctx).Update(tag, &entity.Tag{ID: tag.ID}); err != nil {
    return fmt.Errorf("update tag failed: %w", err)
}
// after
if _, err = x.Context(ctx).Cols("question_count").Update(tag, &entity.Tag{ID: tag.ID}); err != nil {
    return fmt.Errorf("update tag failed: %w", err)
}
Defensive patterns

Strategy: retry

Validate before calling

if has, _ := x.Context(ctx).IsColumnExist("tag", "question_count"); !has {
    return fmt.Errorf("tag.question_count column missing; apply DDL first")
}

Try / catch

if _, err = x.Context(ctx).Update(tag, &entity.Tag{ID: tag.ID}); err != nil {
    if isRetryable(err) { // e.g. lock wait timeout / connection reset
        time.Sleep(time.Second)
        _, err = x.Context(ctx).Update(tag, &entity.Tag{ID: tag.ID})
    }
    if err != nil { return fmt.Errorf("update tag failed: %w", err) }
}

Prevention

When it happens

Trigger: x.Context(ctx).Update(tag, &entity.Tag{ID: tag.ID}) failing mid-loop due to connection drop, missing question_count column, row lock contention, or cancelled context.

Common situations: Large tag tables updated one-by-one over unreliable connections; concurrent tag updates causing lock waits; running before the schema change added question_count.

Related errors


AI-assisted analysis of apache/answer@3b9f137061 (2026-09-05). Data as JSON: /api/errors/3ece562d4cd1b50d. Report an issue: GitHub.