# Client tags not shown when working in the Project Library

**URL:** <https://forum.inductiveautomation.com/t/client-tags-not-shown-when-working-in-the-project-library/107059>\
**Category:** Ignition\
**Tags:** vision\
**Created:** [June 4, 2025, 9:08pm UTC](https://forum.inductiveautomation.com/t/client-tags-not-shown-when-working-in-the-project-library/107059 "2025-06-04T21:08:00Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![Check](https://avatars.discourse-cdn.com/v4/letter/c/e19adc/32.png) [@Check](https://forum.inductiveautomation.com/u/Check)\
**Post date:** [June 4, 2025, 9:08pm UTC](https://forum.inductiveautomation.com/t/client-tags-not-shown-when-working-in-the-project-library/107059/1 "2025-06-04T21:08:00Z")

</div>

Why aren't client tags shown in the Tag Browser when working in the Project Library?  
When I write scripts in the Project Library, I don't see client tags listed in the Tag Browser. I have to manually type the tag paths, which is inconvenient and increases the chance of typos. Is there a reason for this behavior? Is there any way to make client tags visible while working in the Project Library?

 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/c/4/c48a4321f147b219cf82e330fd8405cd6e5c9a7d.png)

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [June 4, 2025, 9:14pm UTC](https://forum.inductiveautomation.com/t/client-tags-not-shown-when-working-in-the-project-library/107059/2 "2025-06-04T21:14:36Z")

</div>

The script library is present independently in all scopes, but Vision Client Tags are only present in Vision scope.

The designer tree has to have something selected under Vision for the tag browser to show Vision Client Tags.

The workaround is to float your project library script windows then pick a Vision item in the tree. Your tag browser will then include Vision Client Tags while your project library scripts remain editable. (Right click on the script's tab at the bottom of the editor to find the float option.)

---

<div class="post-metadata">

**Author:** ![Check](https://avatars.discourse-cdn.com/v4/letter/c/e19adc/32.png) [@Check](https://forum.inductiveautomation.com/u/Check)\
**Post date:** [June 4, 2025, 9:34pm UTC](https://forum.inductiveautomation.com/t/client-tags-not-shown-when-working-in-the-project-library/107059/3 "2025-06-04T21:34:48Z")

</div>

I didn't know I could float the Project Library. Thanks for pointing that out! Now at least I can see my tags while editing, which helps. Still, it would be great to have the reference icons or some way to drag and drop the tags directly into the script like we can elsewhere. Thanks again!

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [June 4, 2025, 9:38pm UTC](https://forum.inductiveautomation.com/t/client-tags-not-shown-when-working-in-the-project-library/107059/4 "2025-06-04T21:38:35Z")

</div>

> [@Check](#):
>
> drag and drop the tags directly into the script

Wherever you feel that desire, consider adding a function argument to carry either the tag value or the tag path. In the actual scope of use, where your event is a one-liner to the project library, you can use the convenience methods in **that** spot to supply the function argument.

Not that you shouldn't have string constants in your project library, but having too many will handcuff your ability to re-use the functions.

---

<div class="post-metadata">

**Author:** ![Check](https://avatars.discourse-cdn.com/v4/letter/c/e19adc/32.png) [@Check](https://forum.inductiveautomation.com/u/Check)\
**Post date:** [June 4, 2025, 10:39pm UTC](https://forum.inductiveautomation.com/t/client-tags-not-shown-when-working-in-the-project-library/107059/5 "2025-06-04T22:39:52Z")

</div>

In my packing application, the user enters the order number, and Ignition calls a stored procedure to retrieve the order data. About 10 tags are populated with the results. The user then makes a few selections on the screen, which update a few more tags. When they click a button to complete packing, it calls a function in the Project Library that reads these tag values to build a dictionary and send it as a payload to an EWM API.

Given this setup, would it be a good practice to pass all 14 values as arguments to the function? Or is there a better way to handle this?

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [June 4, 2025, 10:49pm UTC](https://forum.inductiveautomation.com/t/client-tags-not-shown-when-working-in-the-project-library/107059/6 "2025-06-04T22:49:14Z")

</div>

> [@Check](#):
>
> About 10 tags are populated with the results.

I presume you put these tags in a folder? Just pass the folder path and let the library function construct the full list for `.readBlocking()`.

---

<div class="post-metadata">

**Author:** ![Check](https://avatars.discourse-cdn.com/v4/letter/c/e19adc/32.png) [@Check](https://forum.inductiveautomation.com/u/Check)\
**Post date:** [June 4, 2025, 10:59pm UTC](https://forum.inductiveautomation.com/t/client-tags-not-shown-when-working-in-the-project-library/107059/7 "2025-06-04T22:59:23Z")

</div>

I don't have them in a folder because this application has only one window and is used only for packing, so I don't have multiple groups of tags. So it is not a good practice to read one tag at a time? I'm doing this...  
orderValue1 = system.tag.readBlocking(['[client]orderValue1'])[0].value  
orderValue2 = system.tag.readBlocking(['[client]orderValue2'])[0].value  
orderValue3 = system.tag.readBlocking(['[client]orderValue1'])[0].value

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [June 4, 2025, 11:08pm UTC](https://forum.inductiveautomation.com/t/client-tags-not-shown-when-working-in-the-project-library/107059/8 "2025-06-04T23:08:08Z")

</div>

> [@Check](#):
>
> So it is not a good practice to read one tag at a time?

Terrible practice.

---

<div class="post-metadata">

**Author:** ![paul-griffith](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/paul-griffith/32/37249_2.png) [@paul-griffith](https://forum.inductiveautomation.com/u/paul-griffith)\
**Post date:** [June 4, 2025, 11:48pm UTC](https://forum.inductiveautomation.com/t/client-tags-not-shown-when-working-in-the-project-library/107059/9 "2025-06-04T23:48:30Z")

</div>

Less terrible with client tags, because there's no network hop involved, but it's a bad habit to start.

Consider if you were reading three gateway tags. Because you're using `readBlocking`, you're sending three requests _in series_ - meaning you're paying whatever network latency penalty exists between client and gateway **six** times, rather than **two**. And your script is almost certainly running on the main GUI thread, meaning users won't be able to interact with anything in the client while that's all happening.

**By far** the better practice is to batch your tag reads together into single chunks (if you continue to use blocking reads - going all the way down the async rabbit hole is probably out of scope):

```python
paths = [
	'[client]orderValue1',
	'[client]orderValue2',
	'[client]orderValue3',
]
qvs = system.tag.readBlocking(paths)
orderValue1, orderValue2, orderValue3 = [qv.value for qv in qvs]

```

---

<div class="post-metadata">

**Author:** ![Check](https://avatars.discourse-cdn.com/v4/letter/c/e19adc/32.png) [@Check](https://forum.inductiveautomation.com/u/Check)\
**Post date:** [June 4, 2025, 11:53pm UTC](https://forum.inductiveautomation.com/t/client-tags-not-shown-when-working-in-the-project-library/107059/10 "2025-06-04T23:53:31Z")

</div>

I see, it makes perfect sense. Thank you for the explanation! My question remains unanswered regarding whether I should read the tags in the component and pass 14 arguments to the function, or read the tags within the function itself.

---

<div class="post-metadata">

**Author:** ![nminchin](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/nminchin/32/6911_2.png) [@nminchin](https://forum.inductiveautomation.com/u/nminchin)\
**Post date:** [June 5, 2025, 12:57am UTC](https://forum.inductiveautomation.com/t/client-tags-not-shown-when-working-in-the-project-library/107059/11 "2025-06-05T00:57:30Z")

</div>

> [@Check](#):
>
> So it is not a good practice to read one tag at a time? I'm doing this...

I actually tested this the other day as a colleague new to scripting was doing this, reading one tag at a time. I wanted to show him why it was a bad idea, so I read every tag in the system (only 7639, small project, most opc but maybe 10% memory) both ways: in one list and one-by-one from an, albeit, remote designer script console. The results were a bit staggeringly unexpected to be honest:

- single list read: 650ms
- 1-by-1 single reads: 843,366 ms (14minutes)

_Note: it wouldn't be nearly this bad when running this on the gateway itself, as opposed to across the network through a VPN, but it still won't be great_

Edit:  
Running the same test direct on the gateway (via Perspective):

- single list read: 109ms
- 1-by-1 single reads: 565ms

Still 5x the time

> **Script**
>
> ```python
> from java.lang.System import nanoTime as nt
> tagPaths = system.tag.browse(path='[default]', filter={'tagType': 'AtomicTag', 'recursive': True})
> self.custom.tagCount = len(tagPaths)
> start = nt()
> a = system.tag.readBlocking(str(tag['fullPath']) for tag in tagPaths)
> self.custom.all = (nt()-start)/1000.0/1000.0
> 
> start = nt()
> for tagPath in tagPaths:
> a = system.tag.readBlocking(str(tagPath['fullPath']))
> self.custom.single = (nt()-start)/1000.0/1000.0
> 
> ```

---

<div class="post-metadata">

**Author:** ![Leor\_Fishman](https://avatars.discourse-cdn.com/v4/letter/l/e19adc/32.png) [@Leor\_Fishman](https://forum.inductiveautomation.com/u/Leor_Fishman)\
**Post date:** [June 5, 2025, 1:41am UTC](https://forum.inductiveautomation.com/t/client-tags-not-shown-when-working-in-the-project-library/107059/12 "2025-06-05T01:41:07Z")

</div>

if a function has more than 5 arguments, you're going to call it with arguments in the wrong order/with the wrong keyword params at some point, and 5 is pushing it.

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [June 5, 2025, 10:37am UTC](https://forum.inductiveautomation.com/t/client-tags-not-shown-when-working-in-the-project-library/107059/13 "2025-06-05T10:37:42Z")

</div>

> [@Check](#):
>
> read the tags within the function itself.

This, but pass the tag paths as a single argument: a list of strings.

---

<div class="post-metadata">

**Author:** ![Check](https://avatars.discourse-cdn.com/v4/letter/c/e19adc/32.png) [@Check](https://forum.inductiveautomation.com/u/Check)\
**Post date:** [June 6, 2025, 5:49pm UTC](https://forum.inductiveautomation.com/t/client-tags-not-shown-when-working-in-the-project-library/107059/14 "2025-06-06T17:49:50Z")

</div>

I ran your test on my application, and here are the results. It's a small, single-window project with 14 client memory tags, so there's no client-Gateway communication involved when reading them, which aligns with what @paul-griffith mentioned.

That said, I now understand the performance difference once network traffic comes into play in a more complex project. I'm glad I asked—thanks to everyone for the feedback!

| List read (ms) | 1-by-1 read (ms) |
| --- | --- |
| 1 | 2 |
| 1 | 3 |
| 1 | 2 |
| 1 | 4 |
| 0 | 1 |
| 0 | 4 |
| 1 | 2 |
| 0 | 2 |
| 0 | 2 |
| 0 | 1 |

---

<div class="post-metadata">

**Author:** ![Check](https://avatars.discourse-cdn.com/v4/letter/c/e19adc/32.png) [@Check](https://forum.inductiveautomation.com/u/Check)\
**Post date:** [June 6, 2025, 5:58pm UTC](https://forum.inductiveautomation.com/t/client-tags-not-shown-when-working-in-the-project-library/107059/15 "2025-06-06T17:58:08Z")

</div>

If five arguments is already pushing it, what would you suggest for a case where the user clicks a button and the application needs to build a dictionary with 14 values to send to an API? I'm trying to find the right balance between readability and maintainability.

---

<div class="post-metadata">

**Author:** ![pascal.fragnoud](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pascal.fragnoud/32/24728_2.png) [@pascal.fragnoud](https://forum.inductiveautomation.com/u/pascal.fragnoud)\
**Post date:** [June 6, 2025, 7:16pm UTC](https://forum.inductiveautomation.com/t/client-tags-not-shown-when-working-in-the-project-library/107059/16 "2025-06-06T19:16:09Z")

</div>

What are the parameters ?  
Remember you can pass lists and dicts.

---

<div class="post-metadata">

**Author:** ![Leor\_Fishman](https://avatars.discourse-cdn.com/v4/letter/l/e19adc/32.png) [@Leor\_Fishman](https://forum.inductiveautomation.com/u/Leor_Fishman)\
**Post date:** [June 6, 2025, 8:04pm UTC](https://forum.inductiveautomation.com/t/client-tags-not-shown-when-working-in-the-project-library/107059/17 "2025-06-06T20:04:25Z")

</div>

build an object that contains those values, pass the object.

---

<div class="post-metadata">

**Author:** ![Check](https://avatars.discourse-cdn.com/v4/letter/c/e19adc/32.png) [@Check](https://forum.inductiveautomation.com/u/Check)\
**Post date:** [June 6, 2025, 8:35pm UTC](https://forum.inductiveautomation.com/t/client-tags-not-shown-when-working-in-the-project-library/107059/18 "2025-06-06T20:35:27Z")

</div>

Yes, @pturmel already suggested to send a tag path list.

---

<div class="post-metadata">

**Author:** ![pascal.fragnoud](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pascal.fragnoud/32/24728_2.png) [@pascal.fragnoud](https://forum.inductiveautomation.com/u/pascal.fragnoud)\
**Post date:** [June 6, 2025, 8:38pm UTC](https://forum.inductiveautomation.com/t/client-tags-not-shown-when-working-in-the-project-library/107059/19 "2025-06-06T20:38:13Z")

</div>

I was answering to the message just above, about building a dict for an API.  
What's the situation exactly ?  
What data do you need to pass to what ?

---

<div class="post-metadata">

**Author:** ![Check](https://avatars.discourse-cdn.com/v4/letter/c/e19adc/32.png) [@Check](https://forum.inductiveautomation.com/u/Check)\
**Post date:** [June 6, 2025, 9:16pm UTC](https://forum.inductiveautomation.com/t/client-tags-not-shown-when-working-in-the-project-library/107059/20 "2025-06-06T21:16:34Z")

</div>

Here is the situation. Get 10 values from a database (10 tags). User makes 4 selections (4 tags) and clicks on a button. The button builds a dictionary with all 14 values and sends it to an EWM API.

> [@Client tags not shown when working in the Project Library](https://forum.inductiveautomation.com/t/client-tags-not-shown-when-working-in-the-project-library/107059/5):
>
> In my packing application, the user enters the order number, and Ignition calls a stored procedure to retrieve the order data. About 10 tags are populated with the results. The user then makes a few selections on the screen, which update a few more tags. When they click a button to complete packing, it calls a function in the Project Library that reads these tag values to build a dictionary and send it as a payload to an EWM API. Given this setup, would it be a good practice to pass all 14 valu…

[Next page](https://forum.inductiveautomation.com/t/client-tags-not-shown-when-working-in-the-project-library/107059.md?page=2)
