fix: add comprehensive error handling to Present Characters HTML building
PROBLEM (from Salixfire's debug logs):
- Parser successfully extracted 5 characters
- Log showed complete characters array
- Log stopped abruptly before "✓ HTML rendered to container"
- This indicates exception thrown during HTML building (lines 217-281)
DIAGNOSIS:
- Parsing works perfectly (5 characters extracted)
- Code crashes somewhere in the HTML building loop
- User sees placeholder because exception prevents HTML from rendering
- No error logs because crash happens silently
LIKELY CAUSES:
- getGroupMembers() throwing exception
- Character avatar lookup failing
- getSafeThumbnailUrl() failing
- Missing null checks
SOLUTION:
Added comprehensive error handling and debug logging:
1. Added logging before HTML building starts
- "Starting HTML generation for N characters"
- This confirms code reaches HTML building phase
2. Wrapped each character in try-catch
- Logs each character being processed: "Building HTML for character 1/5: Lady Julia"
- Prevents one character error from crashing entire function
- Code continues with other characters even if one fails
3. Added detailed avatar lookup logging:
- "Looking up avatar for: {name}"
- "In group chat, checking group members..."
- "Group members count: N"
- "Found avatar in group members/all characters/current character"
- Shows final avatar URL (first 50 chars)
4. Wrapped getGroupMembers() in try-catch
- Catches group-specific errors
- Logs error but continues with regular character lookup
5. Added success/error logging for each character:
- "✓ Successfully built HTML for {name}"
- "✗ ERROR building HTML for {name}: {error.message}"
- Logs full error stack for debugging
6. Added completion log:
- "Finished building all character cards"
- Confirms loop completed successfully
EXPECTED OUTCOME:
Next debug log from Salixfire will show EXACTLY:
- Which character is causing the crash (if any)
- What operation is failing (avatar lookup, HTML building, etc.)
- Full error message and stack trace
- Whether code completes or crashes
This will allow us to identify and fix the root cause.
Files changed:
- src/systems/rendering/thoughts.js: Added try-catch blocks and comprehensive logging
This commit is contained in:
@@ -177,6 +177,9 @@ export function renderThoughts() {
|
||||
// Build HTML
|
||||
let html = '';
|
||||
|
||||
debugLog('[RPG Thoughts] ==================== BUILDING HTML ====================');
|
||||
debugLog('[RPG Thoughts] Starting HTML generation for', presentCharacters.length + ' characters');
|
||||
|
||||
// If no characters parsed, show a placeholder editable card
|
||||
if (presentCharacters.length === 0) {
|
||||
debugLog('[RPG Thoughts] ⚠ No characters parsed - showing placeholder card');
|
||||
@@ -214,70 +217,106 @@ export function renderThoughts() {
|
||||
html += '</div>';
|
||||
} else {
|
||||
html += '<div class="rpg-thoughts-content">';
|
||||
|
||||
let characterIndex = 0;
|
||||
for (const char of presentCharacters) {
|
||||
// Find character portrait
|
||||
// Use a base64-encoded SVG placeholder as fallback to avoid 400 errors
|
||||
let characterPortrait = FALLBACK_AVATAR_DATA_URI;
|
||||
characterIndex++;
|
||||
|
||||
// console.log('[RPG Companion] Looking for avatar for:', char.name);
|
||||
try {
|
||||
debugLog(`[RPG Thoughts] Building HTML for character ${characterIndex}/${presentCharacters.length}:`, char.name);
|
||||
|
||||
// For group chats, search through group members first
|
||||
if (selected_group) {
|
||||
const groupMembers = getGroupMembers(selected_group);
|
||||
const matchingMember = groupMembers.find(member =>
|
||||
member && member.name && namesMatch(member.name, char.name)
|
||||
);
|
||||
// Find character portrait
|
||||
// Use a base64-encoded SVG placeholder as fallback to avoid 400 errors
|
||||
let characterPortrait = FALLBACK_AVATAR_DATA_URI;
|
||||
|
||||
if (matchingMember && matchingMember.avatar && matchingMember.avatar !== 'none') {
|
||||
const thumbnailUrl = getSafeThumbnailUrl('avatar', matchingMember.avatar);
|
||||
if (thumbnailUrl) {
|
||||
characterPortrait = thumbnailUrl;
|
||||
debugLog(`[RPG Thoughts] Looking up avatar for: ${char.name}`);
|
||||
|
||||
// For group chats, search through group members first
|
||||
if (selected_group) {
|
||||
debugLog('[RPG Thoughts] In group chat, checking group members...');
|
||||
|
||||
try {
|
||||
const groupMembers = getGroupMembers(selected_group);
|
||||
debugLog('[RPG Thoughts] Group members count:', groupMembers ? groupMembers.length : 0);
|
||||
|
||||
if (groupMembers && groupMembers.length > 0) {
|
||||
const matchingMember = groupMembers.find(member =>
|
||||
member && member.name && namesMatch(member.name, char.name)
|
||||
);
|
||||
|
||||
if (matchingMember && matchingMember.avatar && matchingMember.avatar !== 'none') {
|
||||
const thumbnailUrl = getSafeThumbnailUrl('avatar', matchingMember.avatar);
|
||||
if (thumbnailUrl) {
|
||||
characterPortrait = thumbnailUrl;
|
||||
debugLog('[RPG Thoughts] Found avatar in group members');
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (groupError) {
|
||||
debugLog('[RPG Thoughts] Error checking group members:', groupError.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// For regular chats or if not found in group, search all characters
|
||||
if (characterPortrait === FALLBACK_AVATAR_DATA_URI && characters && characters.length > 0) {
|
||||
const matchingCharacter = characters.find(c =>
|
||||
c && c.name && namesMatch(c.name, char.name)
|
||||
);
|
||||
// For regular chats or if not found in group, search all characters
|
||||
if (characterPortrait === FALLBACK_AVATAR_DATA_URI && characters && characters.length > 0) {
|
||||
debugLog('[RPG Thoughts] Searching all characters...');
|
||||
|
||||
if (matchingCharacter && matchingCharacter.avatar && matchingCharacter.avatar !== 'none') {
|
||||
const thumbnailUrl = getSafeThumbnailUrl('avatar', matchingCharacter.avatar);
|
||||
if (thumbnailUrl) {
|
||||
characterPortrait = thumbnailUrl;
|
||||
const matchingCharacter = characters.find(c =>
|
||||
c && c.name && namesMatch(c.name, char.name)
|
||||
);
|
||||
|
||||
if (matchingCharacter && matchingCharacter.avatar && matchingCharacter.avatar !== 'none') {
|
||||
const thumbnailUrl = getSafeThumbnailUrl('avatar', matchingCharacter.avatar);
|
||||
if (thumbnailUrl) {
|
||||
characterPortrait = thumbnailUrl;
|
||||
debugLog('[RPG Thoughts] Found avatar in all characters');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If this is the current character in a 1-on-1 chat, use their portrait
|
||||
if (this_chid !== undefined && characters[this_chid] &&
|
||||
characters[this_chid].name && namesMatch(characters[this_chid].name, char.name)) {
|
||||
const thumbnailUrl = getSafeThumbnailUrl('avatar', characters[this_chid].avatar);
|
||||
if (thumbnailUrl) {
|
||||
characterPortrait = thumbnailUrl;
|
||||
// If this is the current character in a 1-on-1 chat, use their portrait
|
||||
if (this_chid !== undefined && characters[this_chid] &&
|
||||
characters[this_chid].name && namesMatch(characters[this_chid].name, char.name)) {
|
||||
const thumbnailUrl = getSafeThumbnailUrl('avatar', characters[this_chid].avatar);
|
||||
if (thumbnailUrl) {
|
||||
characterPortrait = thumbnailUrl;
|
||||
debugLog('[RPG Thoughts] Found avatar from current character');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Get relationship emoji
|
||||
const relationshipEmoji = relationshipEmojis[char.relationship] || '⚖️';
|
||||
debugLog(`[RPG Thoughts] Final avatar for ${char.name}:`, characterPortrait.substring(0, 50) + '...');
|
||||
|
||||
html += `
|
||||
<div class="rpg-character-card" data-character-name="${char.name}">
|
||||
<div class="rpg-character-avatar">
|
||||
<img src="${characterPortrait}" alt="${char.name}" onerror="this.style.opacity='0.5';this.onerror=null;" />
|
||||
<div class="rpg-relationship-badge rpg-editable" contenteditable="true" data-character="${char.name}" data-field="relationship" title="Click to edit (use emoji: ⚔️ ⚖️ ⭐ ❤️)">${relationshipEmoji}</div>
|
||||
</div>
|
||||
<div class="rpg-character-info">
|
||||
<div class="rpg-character-header">
|
||||
<span class="rpg-character-emoji rpg-editable" contenteditable="true" data-character="${char.name}" data-field="emoji" title="Click to edit emoji">${char.emoji}</span>
|
||||
<span class="rpg-character-name rpg-editable" contenteditable="true" data-character="${char.name}" data-field="name" title="Click to edit name">${char.name}</span>
|
||||
// Get relationship emoji
|
||||
const relationshipEmoji = relationshipEmojis[char.relationship] || '⚖️';
|
||||
|
||||
debugLog(`[RPG Thoughts] Building HTML card for ${char.name}...`);
|
||||
|
||||
html += `
|
||||
<div class="rpg-character-card" data-character-name="${char.name}">
|
||||
<div class="rpg-character-avatar">
|
||||
<img src="${characterPortrait}" alt="${char.name}" onerror="this.style.opacity='0.5';this.onerror=null;" />
|
||||
<div class="rpg-relationship-badge rpg-editable" contenteditable="true" data-character="${char.name}" data-field="relationship" title="Click to edit (use emoji: ⚔️ ⚖️ ⭐ ❤️)">${relationshipEmoji}</div>
|
||||
</div>
|
||||
<div class="rpg-character-info">
|
||||
<div class="rpg-character-header">
|
||||
<span class="rpg-character-emoji rpg-editable" contenteditable="true" data-character="${char.name}" data-field="emoji" title="Click to edit emoji">${char.emoji}</span>
|
||||
<span class="rpg-character-name rpg-editable" contenteditable="true" data-character="${char.name}" data-field="name" title="Click to edit name">${char.name}</span>
|
||||
</div>
|
||||
<div class="rpg-character-traits rpg-editable" contenteditable="true" data-character="${char.name}" data-field="traits" title="Click to edit traits">${char.traits}</div>
|
||||
</div>
|
||||
<div class="rpg-character-traits rpg-editable" contenteditable="true" data-character="${char.name}" data-field="traits" title="Click to edit traits">${char.traits}</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
`;
|
||||
|
||||
debugLog(`[RPG Thoughts] ✓ Successfully built HTML for ${char.name}`);
|
||||
|
||||
} catch (charError) {
|
||||
debugLog(`[RPG Thoughts] ✗ ERROR building HTML for ${char.name}:`, charError.message);
|
||||
debugLog('[RPG Thoughts] Error stack:', charError.stack);
|
||||
// Continue with next character instead of crashing
|
||||
}
|
||||
}
|
||||
|
||||
debugLog('[RPG Thoughts] Finished building all character cards');
|
||||
html += '</div>';
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user