--- old-argh/lib/rb-util.h	2006-03-14 21:04:18.000000000 +1000
+++ new-argh/lib/rb-util.h	2006-03-14 21:04:18.000000000 +1000
@@ -59,6 +59,8 @@ GList* rb_string_list_copy (GList *list)
 GList* rb_collate_hash_table_keys (GHashTable *table);
 GList* rb_collate_hash_table_values (GHashTable *table);
 
+char *rb_make_valid_utf8 (const char *text);
+
 G_END_DECLS
 
 #endif /* __RB_UTIL_H */

--- old-argh/lib/rb-util.c	2006-03-14 21:04:18.000000000 +1000
+++ new-argh/lib/rb-util.c	2006-03-14 21:04:18.000000000 +1000
@@ -667,3 +667,41 @@ rb_collate_hash_table_values (GHashTable
 
 	return list;
 }
+
+/* stolen from gnome-vfs/gnome-vfs-util.c */
+char *
+rb_make_valid_utf8 (const char *text)
+{
+	GString *string;
+	const char *remainder, *invalid;
+	int remaining_bytes, valid_bytes;
+
+	string = NULL;
+	remainder = text;
+	remaining_bytes = strlen (text);
+
+	while (remaining_bytes != 0) {
+		if (g_utf8_validate (remainder, remaining_bytes, &invalid)) {
+			break;
+		}
+		valid_bytes = invalid - remainder;
+
+		if (string == NULL) {
+			string = g_string_sized_new (remaining_bytes);
+		}
+		g_string_append_len (string, remainder, valid_bytes);
+		g_string_append_c (string, '?');
+
+		remaining_bytes -= valid_bytes + 1;
+		remainder = invalid + 1;
+	}
+
+	if (string == NULL)
+		return NULL;
+
+	g_string_append (string, remainder);
+	g_assert (g_utf8_validate (string->str, -1, NULL));
+
+	return g_string_free (string, FALSE);
+}
+

--- old-argh/rhythmdb/rhythmdb.c	2006-03-14 21:04:18.000000000 +1000
+++ new-argh/rhythmdb/rhythmdb.c	2006-03-14 21:04:18.000000000 +1000
@@ -2456,17 +2456,29 @@ rhythmdb_entry_set_uninserted (RhythmDB 
 static void
 rhythmdb_entry_set_internal (RhythmDB *db, RhythmDBEntry *entry,
 			     gboolean notify_if_inserted,
-			     guint propid, const GValue *value)
+			     guint propid, const GValue *in_value)
 {
 	RhythmDBClass *klass = RHYTHMDB_GET_CLASS (db);
 	gboolean handled;
+	GValue fixed_value = {0,};
+	const GValue *value = in_value;
 
 #ifndef G_DISABLE_ASSERT	
 	switch (G_VALUE_TYPE (value)) {
 	case G_TYPE_STRING:
-		/* the playback error is allowed to be NULL */
-		if (propid != RHYTHMDB_PROP_PLAYBACK_ERROR || g_value_get_string (value))
-			g_assert (g_utf8_validate (g_value_get_string (value), -1, NULL));
+		{
+			/* make sure the string is valid utf8 */
+			const char *str = g_value_get_string (value);
+			if (propid != RHYTHMDB_PROP_PLAYBACK_ERROR || str != NULL) {
+				char *valid_utf8 = rb_make_valid_utf8 (str);
+				if (valid_utf8) {
+					g_print ("!!! converted \"%s\" to \"%s\"\n", str, valid_utf8);
+					g_value_init (&fixed_value, G_TYPE_STRING);
+					g_value_take_string (&fixed_value, valid_utf8);
+					value = &fixed_value;
+				}
+			}
+		}
 		break;
 	case G_TYPE_BOOLEAN:
 	case G_TYPE_ULONG:
@@ -2624,6 +2636,11 @@ rhythmdb_entry_set_internal (RhythmDB *d
 	
 	/* set the dirty state */
 	db->priv->dirty = TRUE;
+
+	/* clean up the modified value, if we made one */
+	if (value != in_value) {
+		g_value_unset (&fixed_value);
+	}
 }
 
 /**

