From ebf22ece8a1f9387dd141b224e6943ab99f0ef4e Mon Sep 17 00:00:00 2001 From: Waleed Latif Date: Fri, 6 Mar 2026 15:25:29 -0800 Subject: [PATCH 1/3] fix(selectors): resolve env var references at design time for selector context Selectors now resolve {{ENV_VAR}} references before building context and returning dependency values to consumers, enabling env-var-based credentials (e.g. {{SLACK_BOT_TOKEN}}) to work with selector dropdowns. Co-Authored-By: Claude Opus 4.6 --- .../sub-block/hooks/use-selector-setup.ts | 31 ++++++++++++++++--- .../sim/hooks/selectors/use-selector-query.ts | 20 +++++++++--- 2 files changed, 42 insertions(+), 9 deletions(-) diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-selector-setup.ts b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-selector-setup.ts index e9acaca7dc..4a46f98d04 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-selector-setup.ts +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-selector-setup.ts @@ -3,8 +3,9 @@ import { useMemo } from 'react' import { useParams } from 'next/navigation' import type { SubBlockConfig } from '@/blocks/types' -import { isEnvVarReference, isReference } from '@/executor/constants' +import { extractEnvVarName, isEnvVarReference, isReference } from '@/executor/constants' import type { SelectorContext, SelectorKey } from '@/hooks/selectors/types' +import { useEnvironmentStore } from '@/stores/settings/environment' import { useWorkflowRegistry } from '@/stores/workflows/registry/store' import { useDependsOnGate } from './use-depends-on-gate' @@ -30,23 +31,43 @@ export function useSelectorSetup( const activeWorkflowId = useWorkflowRegistry((s) => s.activeWorkflowId) const workflowId = (params?.workflowId as string) || activeWorkflowId || '' + const envVariables = useEnvironmentStore((s) => s.variables) + const { finalDisabled, dependencyValues, canonicalIndex } = useDependsOnGate( blockId, subBlock, opts ) + const resolvedDependencyValues = useMemo(() => { + const resolved: Record = {} + for (const [key, value] of Object.entries(dependencyValues)) { + if (value === null || value === undefined) { + resolved[key] = value + continue + } + const str = String(value) + if (isEnvVarReference(str)) { + const varName = extractEnvVarName(str) + resolved[key] = envVariables[varName]?.value ?? value + } else { + resolved[key] = value + } + } + return resolved + }, [dependencyValues, envVariables]) + const selectorContext = useMemo(() => { const context: SelectorContext = { workflowId, mimeType: subBlock.mimeType, } - for (const [depKey, value] of Object.entries(dependencyValues)) { + for (const [depKey, value] of Object.entries(resolvedDependencyValues)) { if (value === null || value === undefined) continue const strValue = String(value) if (!strValue) continue - if (isReference(strValue) || isEnvVarReference(strValue)) continue + if (isReference(strValue)) continue const canonicalParamId = canonicalIndex.canonicalIdBySubBlockId[depKey] ?? depKey @@ -58,14 +79,14 @@ export function useSelectorSetup( } return context - }, [dependencyValues, canonicalIndex, workflowId, subBlock.mimeType]) + }, [resolvedDependencyValues, canonicalIndex, workflowId, subBlock.mimeType]) return { selectorKey: (subBlock.selectorKey ?? null) as SelectorKey | null, selectorContext, allowSearch: subBlock.selectorAllowSearch ?? true, disabled: finalDisabled || !subBlock.selectorKey, - dependencyValues, + dependencyValues: resolvedDependencyValues, } } diff --git a/apps/sim/hooks/selectors/use-selector-query.ts b/apps/sim/hooks/selectors/use-selector-query.ts index 4ed0770cdc..8e124e43f8 100644 --- a/apps/sim/hooks/selectors/use-selector-query.ts +++ b/apps/sim/hooks/selectors/use-selector-query.ts @@ -1,8 +1,9 @@ import { useMemo } from 'react' import { useQuery } from '@tanstack/react-query' -import { isEnvVarReference, isReference } from '@/executor/constants' +import { extractEnvVarName, isEnvVarReference, isReference } from '@/executor/constants' import { getSelectorDefinition, mergeOption } from '@/hooks/selectors/registry' import type { SelectorKey, SelectorOption, SelectorQueryArgs } from '@/hooks/selectors/types' +import { useEnvironmentStore } from '@/stores/settings/environment' interface SelectorHookArgs extends Omit { search?: string @@ -30,14 +31,25 @@ export function useSelectorOptionDetail( key: SelectorKey, args: SelectorHookArgs & { detailId?: string } ) { + const envVariables = useEnvironmentStore((s) => s.variables) const definition = getSelectorDefinition(key) + + const resolvedDetailId = useMemo(() => { + if (!args.detailId) return undefined + if (isReference(args.detailId)) return undefined + if (isEnvVarReference(args.detailId)) { + const varName = extractEnvVarName(args.detailId) + return envVariables[varName]?.value || undefined + } + return args.detailId + }, [args.detailId, envVariables]) + const queryArgs: SelectorQueryArgs = { key, context: args.context, - detailId: args.detailId, + detailId: resolvedDetailId, } - const hasRealDetailId = - Boolean(args.detailId) && !isReference(args.detailId!) && !isEnvVarReference(args.detailId!) + const hasRealDetailId = Boolean(resolvedDetailId) const baseEnabled = hasRealDetailId && definition.fetchById !== undefined ? definition.enabled From 7897e5e4652144a466926fc0495f2bbf091da7e9 Mon Sep 17 00:00:00 2001 From: Waleed Latif Date: Fri, 6 Mar 2026 15:31:54 -0800 Subject: [PATCH 2/3] fix(selectors): prevent unresolved env var templates from leaking into context - Fall back to undefined instead of raw template string when env var is missing from store, so the null-check in the context loop discards it - Use resolvedDetailId in query cache key so React Query refetches when the underlying env var value changes Co-Authored-By: Claude Opus 4.6 --- .../editor/components/sub-block/hooks/use-selector-setup.ts | 2 +- apps/sim/hooks/selectors/use-selector-query.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-selector-setup.ts b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-selector-setup.ts index 4a46f98d04..b70f4d8deb 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-selector-setup.ts +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-selector-setup.ts @@ -49,7 +49,7 @@ export function useSelectorSetup( const str = String(value) if (isEnvVarReference(str)) { const varName = extractEnvVarName(str) - resolved[key] = envVariables[varName]?.value ?? value + resolved[key] = envVariables[varName]?.value ?? undefined } else { resolved[key] = value } diff --git a/apps/sim/hooks/selectors/use-selector-query.ts b/apps/sim/hooks/selectors/use-selector-query.ts index 8e124e43f8..6486e76977 100644 --- a/apps/sim/hooks/selectors/use-selector-query.ts +++ b/apps/sim/hooks/selectors/use-selector-query.ts @@ -59,7 +59,7 @@ export function useSelectorOptionDetail( const enabled = args.enabled ?? baseEnabled const query = useQuery({ - queryKey: [...definition.getQueryKey(queryArgs), 'detail', args.detailId ?? 'none'], + queryKey: [...definition.getQueryKey(queryArgs), 'detail', resolvedDetailId ?? 'none'], queryFn: () => definition.fetchById!(queryArgs), enabled, staleTime: definition.staleTime ?? 300_000, From 04d1f03346871202e1ed25bc45a481cff1cfb533 Mon Sep 17 00:00:00 2001 From: Waleed Latif Date: Fri, 6 Mar 2026 15:45:51 -0800 Subject: [PATCH 3/3] fix(selectors): use || for consistent empty-string env var handling Align use-selector-setup.ts with use-selector-query.ts by using || instead of ?? so empty-string env var values are treated as unset. Co-Authored-By: Claude Opus 4.6 --- .../editor/components/sub-block/hooks/use-selector-setup.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-selector-setup.ts b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-selector-setup.ts index b70f4d8deb..cdbf1e17b6 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-selector-setup.ts +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-selector-setup.ts @@ -49,7 +49,7 @@ export function useSelectorSetup( const str = String(value) if (isEnvVarReference(str)) { const varName = extractEnvVarName(str) - resolved[key] = envVariables[varName]?.value ?? undefined + resolved[key] = envVariables[varName]?.value || undefined } else { resolved[key] = value }