Skip to content

Commit e38b27b

Browse files
committed
fix: use generateId() utility for all client-side UUID generation
Comprehensive fix for HTTP deployments (non-secure contexts). crypto.randomUUID() only works in HTTPS contexts. In HTTP deployments (e.g., http://192.168.x.x:3000), it throws TypeError causing white screen. Changes: - Add shared generateId() utility in lib/utils/uuid.ts with automatic fallback: crypto.randomUUID() → getRandomValues → Math.random - Replace all 38 client-side crypto.randomUUID() calls with generateId() across hooks/, stores/, app/chat/, app/workspace/, serializer/, triggers/ - Server-side code (app/api/, lib/auth/, lib/billing/) unchanged - Node.js always has crypto.randomUUID() available Fixes #3393
1 parent a52d7fd commit e38b27b

File tree

39 files changed

+189
-114
lines changed

39 files changed

+189
-114
lines changed

apps/sim/app/chat/[identifier]/chat.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { generateId } from '../../../lib/utils/uuid'
12
'use client'
23

34
import { type RefObject, useCallback, useEffect, useRef, useState } from 'react'
@@ -303,7 +304,7 @@ export default function ChatClient({ identifier }: { identifier: string }) {
303304
setUserHasScrolled(false)
304305

305306
const userMessage: ChatMessage = {
306-
id: crypto.randomUUID(),
307+
id: generateId(),
307308
content: messageToSend || (files && files.length > 0 ? `Sent ${files.length} file(s)` : ''),
308309
type: 'user',
309310
timestamp: new Date(),
@@ -416,7 +417,7 @@ export default function ChatClient({ identifier }: { identifier: string }) {
416417
logger.error('Error sending message:', error)
417418
setIsLoading(false)
418419
const errorMessage: ChatMessage = {
419-
id: crypto.randomUUID(),
420+
id: generateId(),
420421
content: CHAT_ERROR_MESSAGES.GENERIC_ERROR,
421422
type: 'assistant',
422423
timestamp: new Date(),

apps/sim/app/chat/components/input/input.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { generateId } from '../../../../lib/utils/uuid'
12
'use client'
23

34
import type React from 'react'
@@ -147,7 +148,7 @@ export const ChatInput: React.FC<{
147148
}
148149

149150
newFiles.push({
150-
id: crypto.randomUUID(),
151+
id: generateId(),
151152
name: file.name,
152153
size: file.size,
153154
type: file.type,

apps/sim/app/chat/hooks/use-chat-streaming.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { generateId } from '../../../lib/utils/uuid'
12
'use client'
23

34
import { useRef, useState } from 'react'
@@ -141,7 +142,7 @@ export function useChatStreaming() {
141142

142143
// Track which blocks have streamed content (like chat panel)
143144
const messageIdMap = new Map<string, string>()
144-
const messageId = crypto.randomUUID()
145+
const messageId = generateId()
145146
setMessages((prev) => [
146147
...prev,
147148
{

apps/sim/app/workspace/[workspaceId]/providers/global-commands-provider.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { generateId } from '../../../../lib/utils/uuid'
12
'use client'
23

34
import {
@@ -87,7 +88,7 @@ export function GlobalCommandsProvider({ children }: { children: ReactNode }) {
8788
const register = useCallback((commands: GlobalCommand[]) => {
8889
const createdIds: string[] = []
8990
for (const cmd of commands) {
90-
const id = cmd.id ?? crypto.randomUUID()
91+
const id = cmd.id ?? generateId()
9192
const parsed = parseShortcut(cmd.shortcut)
9293
registryRef.current.set(id, {
9394
...cmd,

apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/chat/chat.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { generateId } from '../../../../../../../lib/utils/uuid'
12
'use client'
23

34
import { type KeyboardEvent, useCallback, useEffect, useMemo, useRef, useState } from 'react'
@@ -601,7 +602,7 @@ export function Chat() {
601602
if (typeof result !== 'object') return
602603

603604
if ('stream' in result && result.stream instanceof ReadableStream) {
604-
const responseMessageId = crypto.randomUUID()
605+
const responseMessageId = generateId()
605606
addMessage({
606607
id: responseMessageId,
607608
content: '',
@@ -799,7 +800,7 @@ export function Chat() {
799800
const defaultType = fieldName === 'files' ? 'file[]' : 'string'
800801

801802
return {
802-
id: crypto.randomUUID(),
803+
id: generateId(),
803804
name: fieldName,
804805
type: defaultType,
805806
value: '',
@@ -814,7 +815,7 @@ export function Chat() {
814815

815816
const userId = session?.user?.id || 'unknown'
816817
addToQueue({
817-
id: crypto.randomUUID(),
818+
id: generateId(),
818819
operation: {
819820
operation: 'subblock-update',
820821
target: 'subblock',

apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/chat/hooks/use-chat-file-upload.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { generateId } from '../../../../../../../../lib/utils/uuid'
12
import { useCallback, useState } from 'react'
23

34
export interface ChatFile {
@@ -53,7 +54,7 @@ export function useChatFileUpload() {
5354
}
5455

5556
validNewFiles.push({
56-
id: crypto.randomUUID(),
57+
id: generateId(),
5758
name: file.name,
5859
size: file.size,
5960
type: file.type,

apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/copilot/components/user-input/hooks/use-file-attachments.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { generateId } from '../../../../../../../../../../../../lib/utils/uuid'
12
'use client'
23

34
import { useCallback, useEffect, useRef, useState } from 'react'
@@ -123,7 +124,7 @@ export function useFileAttachments(props: UseFileAttachmentsProps) {
123124
}
124125

125126
const tempFile: AttachedFile = {
126-
id: crypto.randomUUID(),
127+
id: generateId(),
127128
name: file.name,
128129
size: file.size,
129130
type: file.type,

apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/deploy/components/deploy-modal/components/a2a/a2a.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { generateId } from '../../../../../../../../../../../../../lib/utils/uuid'
12
'use client'
23

34
import { useCallback, useEffect, useMemo, useState } from 'react'
@@ -155,7 +156,7 @@ export function A2aDeploy({
155156
// Add input field if missing (for TextPart)
156157
if (missingFields.input) {
157158
newFields.push({
158-
id: crypto.randomUUID(),
159+
id: generateId(),
159160
name: 'input',
160161
type: 'string',
161162
value: '',
@@ -166,7 +167,7 @@ export function A2aDeploy({
166167
// Add data field if missing (for DataPart)
167168
if (missingFields.data) {
168169
newFields.push({
169-
id: crypto.randomUUID(),
170+
id: generateId(),
170171
name: 'data',
171172
type: 'object',
172173
value: '',
@@ -177,7 +178,7 @@ export function A2aDeploy({
177178
// Add files field if missing (for FilePart)
178179
if (missingFields.files) {
179180
newFields.push({
180-
id: crypto.randomUUID(),
181+
id: generateId(),
181182
name: 'files',
182183
type: 'file[]',
183184
value: '',

apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/document-tag-entry/document-tag-entry.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { generateId } from '../../../../../../../../../../../../../lib/utils/uuid'
12
'use client'
23

34
import { useMemo, useRef } from 'react'
@@ -45,7 +46,7 @@ interface DocumentTagEntryProps {
4546
* Creates a new document tag with default values
4647
*/
4748
const createDefaultTag = (): DocumentTag => ({
48-
id: crypto.randomUUID(),
49+
id: generateId(),
4950
tagName: '',
5051
fieldType: 'text',
5152
value: '',

apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/dropdown/dropdown.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { generateId } from '../../../../../../../../../../../../../lib/utils/uuid'
12
import { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react'
23
import isEqual from 'lodash/isEqual'
34
import { useStoreWithEqualityFn } from 'zustand/traditional'
@@ -276,7 +277,7 @@ export const Dropdown = memo(function Dropdown({
276277
fieldType === 'object' || fieldType === 'array' ? JSON.stringify(value, null, 2) : value
277278

278279
return {
279-
id: crypto.randomUUID(),
280+
id: generateId(),
280281
name: key,
281282
type: fieldType,
282283
value: fieldValue,

0 commit comments

Comments
 (0)